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

C语言strtok()函数调用时程序崩溃问题求助

排查strtok调用崩溃的问题

嘿,我来帮你搞定这个崩溃的问题!strtok这函数看着简单,但藏着个很容易踩的坑——它内部靠一个静态变量记录上一次分割的位置,这就给你的循环逻辑埋下了炸弹。

问题根源

你在while循环里每次用fgets覆盖栈上的a数组,但strtok的静态指针还指着a的内存区域呢!如果上一次处理行的时候没把所有令牌都处理完(或者说strtok的状态还停留在a数组里),下一次fgets把a的内容改了,再调用strtok(NULL, "$")就会去访问已经被篡改的内存,直接触发崩溃。

另外还有个潜在风险:如果一行内容超过59个字符(因为a是60字节,fgets要留一个位置存终止符\0),这行会被截断,剩余内容留在文件缓冲区里,下一次fgets读的是截断后的片段,用strtok处理这种不完整的字符串也容易出异常。

修复方案

方案1:处理完当前行所有令牌再循环

每次读取一行后,把这行里所有$分隔的令牌都处理完毕,再去读下一行。当strtok返回NULL时,它的静态状态会重置,不会和下一行的数组冲突。

修改后的代码示例:

void getFile(FILE *fp, TParts *str) {
    char a[60], *b;
    int p = 0, m = 0;
    while(fgets(a, 60, fp) != NULL) {
        // 先去掉换行符,避免把它当成令牌的一部分
        size_t len = strlen(a);
        if (len > 0 && a[len-1] == '\n') {
            a[len-1] = '\0';
        }
        // 拿到第一个令牌
        b = strtok(a, "$");
        // 循环处理所有令牌
        while (b != NULL) {
            // 这里加你处理令牌的逻辑,比如存入str结构体
            // ... 你的业务代码 ...
            // 获取下一个令牌
            b = strtok(NULL, "$");
        }
    }
}

方案2:用线程安全的strtok_r替代strtok

strtok_r是strtok的可重入版本,它不需要静态变量,而是让你自己提供一个指针保存分割状态,彻底解决了静态变量导致的冲突问题,同时也更适合多线程场景。

示例代码:

void getFile(FILE *fp, TParts *str) {
    char a[60], *b, *saveptr;
    int p = 0, m = 0;
    while(fgets(a, 60, fp) != NULL) {
        size_t len = strlen(a);
        if (len > 0 && a[len-1] == '\n') {
            a[len-1] = '\0';
        }
        b = strtok_r(a, "$", &saveptr);
        while (b != NULL) {
            // 处理令牌的逻辑
            // ...
            b = strtok_r(NULL, "$", &saveptr);
        }
    }
}

额外提醒

如果你的文本里有连续的$(比如abc$$def),strtok会把它们当成一个分隔符,不会返回空字符串。如果需要处理这种连续分隔符之间的空内容,那strtok就不太适用了,得手动遍历字符串来分割。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:35:03