You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

strtok_r返回NULL引发段错误问题求助

问题根源分析

你的问题出在混合使用strtok和strtok_r,并且重复使用已经被strtok修改过的原始buffer。

具体来说:

  1. 第一次用strtok遍历buffer时,strtok会将字符串中的所有:分隔符替换成\0来分割子串。比如你的输入字符串3:IBE3674:02-04-2019:...,经过几次strtok调用后,buffer会变成3\0IBE3674\002-04-2019\0...(所有:都被替换为\0)。
  2. 当你后续重新将c2 = buffer,并用strtok_r再次解析时,buffer已经不是原始的完整字符串了——里面的分隔符都被破坏了。所以第一次strtok_r能拿到"3",但第二次调用strtok_r(NULL, ":", &c1)时,因为找不到:(已经被改成\0了),直接返回NULL,这时候调用strlen(c)就会触发段错误。
修复方案

核心思路是:第一次检查匹配时,不要修改原始的buffer,而是使用它的副本;当需要完整解析时,再用未被修改的原始buffer。

修改后的代码示例:

char buffer[500]; 
// 循环读取文件内容
while(fgets(buffer, sizeof(buffer), f) != NULL){
    // 去掉fgets带来的换行符,避免干扰后续解析
    buffer[strcspn(buffer, "\n")] = '\0';

    // 复制原始buffer到临时内存,用于第一次匹配检查,避免修改原buffer
    char *temp_buf = strdup(buffer);
    if (!temp_buf) {
        perror("strdup failed");
        continue;
    }

    char *c = strtok(temp_buf, ":");
    // 跳过前4个字段,拿到第5个字段(origen)
    for(int i = 0; i < 4; i++){
        c = strtok(NULL, ":");
        if (!c) break; // 防御性检查,避免输入格式错误导致崩溃
        printf("%s\n", c);
    }

    int is_match = 0;
    if (c && strcmp(c, argp->origen) == 0){
        c = strtok(NULL, ":");
        if (!c) { free(temp_buf); continue; }
        printf("%s\n", c);
        if(strcmp(c, argp->destino) == 0){
            is_match = 1;
        }
    }

    // 释放临时buffer
    free(temp_buf);

    // 匹配成功,用原始buffer完整解析
    if (is_match){
        lista_vuelo *nodo = malloc(sizeof(lista_vuelo));
        if (!nodo) {
            perror("malloc failed");
            continue;
        }

        char *save_ptr; // strtok_r的保存指针
        char *c = strtok_r(buffer, ":", &save_ptr);
        if (!c) { free(nodo); continue; }
        nodo->IdReg = atoi(c);
        printf("\n%d test\n", nodo->IdReg);

        // 拿到第二个字段(IBE3674)
        c = strtok_r(NULL, ":", &save_ptr);
        if (!c) { free(nodo); continue; } // 防御性检查
        printf("\n%s\n", c); 
        nodo->Idvuelo = strndup(c, strlen(c));

        // ... 后续其他字段的解析逻辑

        // 记得在合适的地方释放nodo和Idvuelo的内存,避免泄漏
    }
}
额外注意事项
  • 防御性检查:每次调用strtok/strtok_r后,都要检查返回值是否为NULL,避免输入格式不符合预期时触发崩溃。
  • 内存管理:strdup和malloc分配的内存,一定要在使用完后用free释放,避免内存泄漏。
  • 换行符处理:fgets会把换行符\n也读入buffer,用strcspn去掉它,避免最后一个字段带有换行符导致比较或解析错误。

内容的提问来源于stack exchange,提问作者Opresor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:26:27