C语言返回字符数组警告“返回本地变量的地址”

6

这是一份作业的部分内容。

我正在尝试在我的getLine方法中读取并返回文件的单行。

char *getLine(FILE *input) {
    char line[30];
    if(fgets(line, sizeof(line), input)!=NULL)
    {
        return line;
    }else{
        return NULL;
    }
}

这似乎是指针相关的内容,但我无法消除警告信息 warning: function returns address of local variable [enabled by default]。该警告指向了return line;这一行。我的任务要求编译时没有警告或错误。我不知道我做错了什么。
大部分帮助建议为文本行分配malloc空间,但我们在课堂上还没有涵盖到这个话题,尽管我在另一个班级中已经做过一些。那真的是最好的方法吗?如果是,我能在程序中任何地方释放它吗?

1
当函数返回时,局部变量将不再存在,然后您会返回一个悬空指针。让我找到一个副本。 - Daniel Fischer
如果你想在堆上分配内存,请使用 malloc。而且这个问题已经在这里被问了无数次。 - KBart
这是一个非常常见的错误,所以你肯定会找到很多关于遇到这个问题的帖子 :) 其中一个原因是大多数编译器甚至不会警告你正在做什么:http://ideone.com/S5Se71 - LihO
这意味着你应该确切地知道自己在做什么 :) - LihO
这个问题是一个重复的副本?什么? - Braden Best
标记为重复的问题实际上并不包含针对此特定问题的答案(代码)。 - hyde
2个回答

14

char line[30]; 是具有自动存储期的数组。一旦执行超出函数作用域,该数组所在的内存将被释放,因此您返回的指向该内存的指针将变为无效(悬空指针)。

试图访问已经被释放的内存会导致未定义的行为

您可以动态分配数组,并让调用者显式地释放它:

char *getLine() {
    char* line = malloc(30);
    ...
    return line;
}

// somewhere:
char* line = getLine();
...
free(line);

1
我应该制作这个答案的模板..;) - KBart

5

在不使用malloc的情况下,提供一种解决方案,之前的问题中似乎没有涉及到:

/* Warning, this function is not re-entrant. It overwrites result of previous call */
char *getLine(FILE *input) {
    static char line[30];
    return fgets(line, sizeof(line), input);
    /* fgets returns NULL on failure, line on success, no need to test it */
}

解释:静态变量函数作用域中保留其值,即使函数返回后也是如此。这样的变量只有一个实例,在调用该函数时使用相同的变量(因此不可重入/线程安全)。静态变量的内存分配发生在程序启动时,它既不在堆栈中,也不在堆中,而是在正在运行的程序的内存空间中拥有自己的保留区域。静态变量的值仅初始化一次,在第一次使用之前进行(上面没有特定的初始化,因此它被填充为0,但它也可以有一个初始化器,那只会是在第一次调用函数时的值)。
尽管以这种方式使用静态变量可能看起来有点狡猾(我同意它是这样的),但它仍然是一种有效的模式,例如标准C也采用了这种方法,比如strtok()函数。它还展示了需要一个可重入版本的需求,因为C标准还有strtok_r(),它更复杂,需要一个额外的参数,而不是在本地静态变量中使用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接