C语言string_split函数初始化char指针数组遇段错误求助
解决string_split函数的段错误问题及正确实现
错误原因分析
- 参数传递错误:
string_split函数中tokens是按值传递的,函数内部malloc分配的地址无法传递回main函数,导致main里的tokens始终是NULL,打印时访问空指针触发段错误。 - Token数量计算错误:
character_count返回的是分隔符的数量,但实际Token数量应该是分隔符数量+1(比如字符串"a\nb\nc"有2个\n,对应3个Token),当前代码malloc的数组大小不足,会导致数组越界访问。 - strtok参数不规范:
strtok的第二个参数要求是字符串(char*指向的以\0结尾的字符序列),虽然传入&del在单个分隔符场景下能工作,但更规范的写法是直接使用字符串字面量或构造合法字符串。
修正后的完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdint.h> char** string_split(char *buffer, char del, uint32_t *out_len); uint32_t character_count(char *str, char c); int main(int argc, char *argv[]) { uint32_t i, len; char *buffer = NULL; long length; FILE *f; char **tokens = NULL; if (argc < 2) { printf("usage: %s <config_file>\n", argv[0]); return 0; } f = fopen(argv[1], "rb"); if (f) { fseek(f, 0, SEEK_END); length = ftell(f); fseek(f, 0, SEEK_SET); buffer = malloc(length + 1); if (buffer) { fread(buffer, 1, length, f); buffer[length] = '\0'; } fclose(f); } if (buffer) { tokens = string_split(buffer, '\n', &len); printf("len:%d\n", len); for(i = 0; i < len; i++) { printf("%s\n", tokens[i]); } // 释放资源,避免内存泄漏 free(tokens); free(buffer); } return 0; } char** string_split(char *buffer, char del, uint32_t *out_len) { uint32_t size, cnt; char *token = NULL; char del_str[2] = {del, '\0'}; // 构造合法的分隔符字符串 cnt = 0; size = character_count(buffer, del) + 1; // 修正Token数量计算 char **tokens = malloc(size * sizeof(char *)); if (!tokens) { *out_len = 0; return NULL; } token = strtok(buffer, del_str); if (token != NULL) { tokens[cnt++] = token; } while ((token = strtok(NULL, del_str)) != NULL) { tokens[cnt++] = token; } *out_len = cnt; return tokens; } uint32_t character_count(char *str, char c) { uint32_t cnt = 0; // 优化遍历方式,避免重复调用strlen while (*str != '\0') { if (*str == c) { cnt++; } str++; } return cnt; }
关键修改说明
- 调整函数接口:将
string_split改为返回char**类型的Token数组,通过指针参数out_len返回Token数量,彻底解决传值导致的地址无法传递问题。 - 修正Token数量计算:在分隔符计数基础上加1,确保
malloc的数组能容纳所有Token,避免越界访问。 - 规范strtok参数:构造包含分隔符的合法字符串
del_str,符合strtok的参数要求。 - 优化性能与内存管理:修改
character_count的遍历方式,避免重复调用strlen;在main中添加资源释放逻辑,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Lee Brown
相关产品推荐
相关产品推荐

