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-ing 空间,但我们还没有在课堂上讨论过这一点,尽管我在另一堂课上做过一些。这真的是最好的方法吗?如果是这样,我可以在程序的任何地方释放吗?

4

2 回答 2

14

char line[30];是一个具有自动存储持续时间的数组。一旦执行超出您的函数范围,它所在的内存就会被释放,因此指向您返回的该内存的指针变得无效(悬空指针)。

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

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

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

// somewhere:
char* line = getLine();
...
free(line);
于 2013-02-14T10:23:18.673 回答
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 填充,但它也可以有一个初始化器,这只是第一次调用函数时的值)。

虽然以这种方式使用静态变量可能看起来有点 hacky(我同意它),但它仍然是标准 C 也采用的有效模式,例如strtok()function。它还表明需要一个可重入的版本,因为 C 标准也有strtok_r(),它使用起来更复杂,因为它有一个额外的参数,而不是其中有局部静态变量。

于 2013-02-14T10:30:40.590 回答