fork数组赋值冲突

Fork array assignment conflict

我有以下内容并尝试逐行读取文件,然后将该行放入数组。

char **history = malloc(sizeof(char*) * 1000);
int history_size = 0;

fp = fopen(file, "r");
if (fp == NULL)
    exit(EXIT_FAILURE);

while ((read = getline(&line, &len, fp)) != -1) {
    if(strstr(line, "\n") != NULL) {
        line[strlen(line) - 1] = '[=10=]';
    }

    if (strcmp(line, "History") == 0) {
        for(int m = 0; m < history_size; m++) {
            printf("%s\n", history[m]);
        }
    } else {
        //printf("....%s\n", line);
        history[history_size++] = line;
    }
}

fclose(fp);
if (line)
    free(line);

问题是数组不收集行,当我 运行 代码打印时 "History" 与文件中的行一样多。我好几天都受不了。历史应该保留历史行之前出现的行。

fork()无关。

来自getlinemanpage

If *lineptr is NULL, then getline() will allocate a buffer for storing the line, which should be freed by the user program. (In this case, the value in *n is ignored.)

If the buffer is not large enough to hold the line, getline() resizes it with realloc(3), updating *lineptr and *n as necessary.

问题是您正在将地址分配给数组元素。最后它们都指向相同的地址(取决于 getlinerealloc)。由于您没有 malloc,因此 getline 必须在内部完成,并且在随后的调用中 reallocgetline 内部使用,这通常会保留相同的地址。因此,随着 line 更新的循环,所有数组元素也可能会更新,因为大多数数组元素指向相同的地址。

所以最后当你达到你的 line"History" 的条件时,他们只是显示了 line 包含的内容(即 "History"),因为他们都指向与 line.

相同的地址

这是问题的主要原因,但是 fork() 肯定会偏离您之后想要的输出方式。尽管 fork() 只会干扰您的输出,并且可以通过在 fork() 返回 0 时不打印来轻松处理。

更正:

1) 正如您在对问题的评论中所说,如果 fork() == 0,您正在做 execvp(),它不应该引起问题。您需要做的就是:

history[history_size] = malloc(sizeof(char)* (strlen(line)+1));
strcpy(history[history_size++], line);

而不是直接赋值

2) 记住在每次迭代中 free()line 中的 getline() 分配的内存。