“与本地变量关联的堆栈存储器的地址”在C中运行用户定义的函数时出错[重复]

问题描述 投票:-1回答:2

最近,我一直在学习哈佛大学的CS50 2020课程,作为C编程的入门。我对语言或整体编码不是很有经验,所以我在努力弄清楚我的代码有什么问题。

我编写了这个小函数,该函数应该接收字符串,然后通过调用另一个函数,使用凯撒密码对文本进行加密,然后将其作为字符串返回。问题是,我不知道如何将字符数组作为字符串返回。在阅读了一些有关该问题的信息后,我尝试在数组的末尾添加一个NUL char,它可以正确编译,但是当我运行该程序时,出现以下错误消息:

error: address of stack memory associated with local variable 'result' returned [-Werror,-Wreturn-stack-address]
    return result;
           ^~~~~~

我的代码:

string encypher(string text)
{
    int length = strlen(text);
    char result[length];
    for(int i = 0; i < length; i++)
    {
        int letter_c = test_char(text[i]);
        result[i] = (char)letter_c;
    }
    result[length + 1] = '\0';
    return result;
}
c arrays clang c-strings cs50
2个回答
1
投票

这里的问题是,result是一个数组,在表达式中使用时会衰减到指向其第一个元素的指针,这就是从函数返回的内容。而且由于函数的返回时间会终止数组的生存期,因此该指针现在指向无效的内存位置,并且尝试使用它会调用undefined behavior

不是创建本地数组,而是使用malloc函数动态分配内存。该内存在程序有效期内有效,或者直到返回的指针传递给free为止有效:

string result = malloc(length + 1);

此外,请注意,您需要为用于终止字符串的空字节预留一个额外的字节。


0
投票

在线

return result;

指向指针的数组decays,因此实际上是以下内容:

return &result[0];

此数组在函数encypher中的堆栈上分配,因此在函数返回时它将不再存在。因此,返回的指针是dangling pointer,这意味着它指向不再分配的内存,并且可能被其他内容覆盖。因此,不应使用此类指针。

为了分配在函数返回后仍然存在的内存,您可以:

  • 使用动态内存分配,例如malloc
  • 在调用malloc的函数的堆栈上分配内存(而不是在函数encypher本身中分配内存,并更改函数encypher的参数以接受指向该数组的指针。

我认为第二种解决方案是更清洁的解决方案,因为它允许调用方决定在何处以及如何分配内存。使用该解决方案,您的代码将如下所示:

encypher

现在可以这样调用该函数:

void encypher( char *cyphertext, const char *plaintext )
{
    int length = strlen(plaintext);
    //removed: char result[length];
    for(int i = 0; i < length; i++)
    {
        int letter_c = test_char(plaintext[i]);
        cyphertext[i] = (char)letter_c;
    }
    cyphertext[length + 1] = '\0';
}
© www.soinside.com 2019 - 2024. All rights reserved.