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
相关产品推荐
相关产品推荐

