getline()/ strsep()组合导致分段错误

Ard*_*ino 3 c getline segmentation-fault strsep

运行下面的代码时,我遇到了分段错误.

它应该基本上读取.csv超过3M线的文件并在之后执行其他操作(与问题无关),但在207746次迭代后它返回分段错误.如果我删除p = strsep(&line,"|");并打印整个line它将打印> 3M线.

int ReadCSV (int argc, char *argv[]){

    char *line = NULL, *p;
    unsigned long count = 0;

    FILE *data;
    if (argc < 2) return 1;
    if((data = fopen(argv[1], "r")) == NULL){
        printf("the CSV file cannot be open");
        exit(0);
    }


    while (getline(&line, &len, data)>0) {

        p = strsep(&line,"|");  

        printf("Line number: %lu \t p: %s\n", count, p);
        count++;
    }

    free(line);
    fclose(data);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我想它与内存分配有关,但无法弄清楚如何修复它.

das*_*ght 6

组合getlinestrsep经常导致混淆,因为两个函数都会将指针传递给指针作为初始参数.如果传递已经通过了该指针strsepgetline一遍,你运行的不确定的行为第二次迭代的风险.

考虑一个示例:getline分配101个字节line,并将100个字符的字符串读入其中.请注意,len现在设置为101.您调用strsep,'|'在字符串的中间找到,因此它指向line以前的内容line+50.现在你getline再打电话.它看到另一个100个字符的行,并得出结论可以将它复制到缓冲区,因为len它仍然是101.但是,由于现在line指向缓冲区的中间,写入100个字符变为未定义的行为.

line在致电之前复制一份strsep:

while (getline(&line, &len, data)>0) {
    char *copy = line;
    p = strsep(&copy, "|");  
    printf("Line number: %lu \t p: %s\n", count, p);
    count++;
}
Run Code Online (Sandbox Code Playgroud)

现在line您传递给getline循环迭代之间保留.