使用strsep分割字符串存储时触发段错误的问题排查
问题分析与解决方案
段错误的核心原因
你的代码存在两个关键问题:
- 未初始化的指针判断:
found变量在第一次循环前没有赋值,直接用while(found!=NULL)做判断,这属于未定义行为,大概率是触发段错误的根源。 - 循环逻辑倒置:
strsep的正确使用流程应该是先调用函数获取分割结果,再判断结果是否为NULL,而非先判断未初始化的指针。
另外,当前写法还存在潜在风险:strsep返回的指针指向strdup分配的临时内存temp,如果后续释放temp,result数组里的所有指针都会变成悬空指针,访问它们会触发未定义行为。
修正后的代码
方式一:临时内存复用(需注意内存释放时机)
如果只是临时使用分割后的单词,不需要持久化,可以保留strdup的临时内存,修正循环逻辑即可:
#include <stdio.h> #include <string.h> #include <stdlib.h> void messtowords(char* string, char** result) { char* temp = strdup(string); if (temp == NULL) { // 检查内存分配是否成功 *result = NULL; return; } char* del = " "; int i = 0; char* in = temp; char* found; // 先调用strsep获取结果,再判断是否继续循环 while ((found = strsep(&in, del)) != NULL) { // 跳过连续空格产生的空字符串 if (*found != '\0') { result[i] = found; i++; } } result[i] = NULL; // 用NULL标记数组末尾,方便后续遍历 } int main(void) { char TC_norep[] = "This is a test string"; char* words[100]; messtowords(TC_norep, words); // 遍历打印所有单词 for (int j = 0; words[j] != NULL; j++) { printf("%s\n", words[j]); } // 所有words指针都指向同一块临时内存,释放一次即可 free(words[0]); return 0; }
方式二:持久化存储单词(避免悬空指针)
如果需要长期保存分割后的单词,应该为每个单词单独分配内存,避免临时内存释放后指针失效:
#include <stdio.h> #include <string.h> #include <stdlib.h> void messtowords(char* string, char** result) { char* temp = strdup(string); if (temp == NULL) { *result = NULL; return; } char* del = " "; int i = 0; char* in = temp; char* found; while ((found = strsep(&in, del)) != NULL) { if (*found != '\0') { // 为每个单词分配独立内存并复制内容 result[i] = strdup(found); i++; } } result[i] = NULL; free(temp); // 临时内存可安全释放 } int main(void) { char TC_norep[] = "This is a test string"; char* words[100]; messtowords(TC_norep, words); for (int j = 0; words[j] != NULL; j++) { printf("%s\n", words[j]); free(words[j]); // 每个单词单独释放内存 } return 0; }
关于字符指针数组的修改问题
你在main里定义的char* words[100]是栈上的指针数组,每个元素都是可修改的char*类型指针。之前的段错误并非因为无法修改数组元素,而是未初始化指针的非法判断引发的未定义行为。
内容的提问来源于stack exchange,提问作者Swiss Gnome
相关产品推荐
相关产品推荐

