strtok第二次调用触发Invalid read of size 1错误排查求助
问题分析与修复方案
错误核心原因:strtok的静态状态被嵌套调用破坏
strtok依赖静态全局变量保存当前分词的位置,这个状态是全局共享的——你在removeDuplicates里正用它切分输入文本,结果调用isDuplicate时,里面又用strtok切分结果字符串,直接把之前的分词位置覆盖了。等回到removeDuplicates再调用strtok(NULL),它会尝试从isDuplicate里已经被释放的soFar内存继续读取,自然触发Invalid read of size 1的内存错误。
顺带提下代码里的冗余问题:compareThem函数完全多余,strcmp已经完成了完整的字符串比较,后面的循环纯属重复劳动;另外结果字符串最后会多一个空格,输出时需要处理。
修复后的代码
换用自定义的分词函数,彻底避开strtok的静态状态坑,同时优化逻辑:
#include <iostream> #include <cstring> using namespace std; // 自定义分词:从start位置找下一个单词,返回单词起始指针,end指向单词后的位置 char* nextWord(char* start, char*& end) { // 跳过开头空格 while (*start != '\0' && *start == ' ') { start++; } if (*start == '\0') { end = start; return nullptr; } end = start; // 找到单词结束位置 while (*end != '\0' && *end != ' ') { end++; } // 临时标记单词结尾为'\0',方便字符串操作 char temp = *end; *end = '\0'; char* word = start; // 恢复原字符 if (temp != '\0') { *end = temp; end++; } return word; } bool isDuplicate(char* possibleDuplicate, char* result) { char* end; char* word = nextWord(result, end); while (word != nullptr) { if (strcmp(possibleDuplicate, word) == 0) { return true; } word = nextWord(end, end); } return false; } void removeDuplicates(char* text) { char* result = new char[1001]; // 多留一位处理结尾空格 result[0] = '\0'; char* end; char* word = nextWord(text, end); while (word != nullptr) { if (!isDuplicate(word, result)) { strcat(result, word); strcat(result, " "); } word = nextWord(end, end); } // 去掉最后一个多余的空格 if (strlen(result) > 0) { result[strlen(result) - 1] = '\0'; } cout << result; delete[] result; } int main() { char* str = new char[1001]; cin.getline(str, 1001); removeDuplicates(str); delete[] str; return 0; }
关键改进点
- 自定义
nextWord函数,用指针参数传递分词上下文,完全避免静态变量冲突。 - 删除冗余的
compareThem函数,直接用strcmp完成字符串比较。 - 处理结果字符串末尾的多余空格,保证输出格式正确。
- 数组大小预留足够空间,防止内存越界。
内容的提问来源于stack exchange,提问作者Astor
相关产品推荐
相关产品推荐

