Realloc覆盖数组的内容?

时间:2014-04-08 04:31:25

标签: c io realloc

我正在尝试使用getline()和realloc()将文件读入字符串数组。我过去使用了非常相似的代码来标记字符串,一切正常。我会将示例输入文件视为

1
2
3
4
5

以下是代码:

char** read_input(const char* input_file, char* line){

    FILE *fp;
    size_t len = 0;
    size_t nums = 0;
    ssize_t read;
    char** res = NULL;

    if ((fp = fopen(input_file, "r")) == NULL){
        printf("Incorrect file\n", strerror(errno));
        exit(EXIT_FAILURE);
    }

    while ((read = getline(&line, &len, fp)) != -1){
        if ((res = realloc(res, sizeof(char*) * ++nums)) == NULL)
            exit(EXIT_FAILURE);

        char to_strip[sizeof(read) * sizeof(char)];
        strcpy(to_strip, line);
        if (line[read - 1] == '\n')
            to_strip[read - 1] = 0;
        else
            line[read] = 0;

        res[nums - 1] = to_strip;
    }
    free(line);

    if ((res = realloc(res, sizeof(char*) * (nums + 1))) == NULL)
        exit(EXIT_FAILURE);

    res[nums - 1] = 0;

    return res;
}

循环之后,如果我打印数组的内容,我得到:

5
5
5
5
5

尽管如果我在循环中调用print,在每次分配到res之后,我得到正确的数字。这真的让我很难过,因为除了realloc之外我无法看到什么是错的,但我认为realloc保留了数组内容。感谢。

2 个答案:

答案 0 :(得分:2)

您正在忙于调用未定义的行为,因为您每次都在重新分配的数组中存储指向to_strip的指针,并且指针在循环的每次迭代时都超出范围,并在每次迭代时被覆盖这就是你最后看到相同价值的原因。如果您在循环中打印了所有值而不仅仅是当前值,那么您首先会看到1,然后是2 2,然后是3 3 3,然后是4 4 4 4,最后是{ {1}}。如果在打印结果之前从此函数返回后做了足够的工作,您会看到垃圾,因为该空间将用于其他目的。

您需要复制存储在重新分配的数组中的行。最简单的方法是使用5 5 5 5 5

strdup()

不要忘记释放字符串以及指向字符串的指针数组。

请不要忘记在您返回之前关闭您打开的文件。

res[nums - 1] = strdup(to_strip); 传递给函数似乎很奇怪。它必须是空指针或指向可以传递给line的空格。既然你在返回之前realloc()空间,那么调用函数需要知道你已经释放它传递给你的空间 - 而且由于你不知道它有多大,你告诉它free()它大小为零,所以它必须被释放。没有该参数,界面会更清晰;在函数开头使用本地getline()

答案 1 :(得分:1)

这是一个问题:

ssize_t read;

char to_strip[sizeof(read) * sizeof(char)];
strcpy(to_strip, line);

sizeof(read) - 可能是4或8 - 是为要复制字符串的缓冲区分配的奇怪数量。我想你的意思是char to_strip[ read + 1 ];。但是,稍后您就有了这句话:

res[nums - 1] = to_strip;

将指向to_strip的指针放入res。但是,to_stripfor循环结束时不再存在,因此这些将是狂野的指针。如果您的目的是存储从文件中读取的所有文本以供以后访问,那么您将需要为每一行分配内存。

Jonathan Leffler对strdup的建议可能是最简单的解决方案;感谢他清除我对getline的错误使用。

您也可以完全取消to_strip,因为您可以直接在\n覆盖line