C语言拼接char*与char触发Segmentation Fault的原因排查
C语言函数段错误(Segmentation Fault)原因解析
你提供的代码在第13行(strncat(buffer, &temp, 1);)崩溃,核心原因集中在scanTString函数的内存管理和字符串操作上,具体如下:
char *scanTString(char *program, size_t *cursor, char delim) { size_t bSize = 0; char *buffer = (char *)malloc(bSize); (*cursor)++; for (; *cursor < strlen(program); ++(*cursor)) { if (program[*cursor] != delim) { buffer = (char *)realloc(buffer, bSize++); char temp; temp = program[*cursor]; strncat(buffer, &temp, 1); } else break; } return buffer; } void tokenize(AST *ast, char *program) { ast->tkSize = 0; for (size_t i = 0; i < strlen(program); i++) { if (program[i] == '\'' || program[i] == '"') { char *scaned = scanTString(program, &i, program[i]); ast->tkSize++; ast->tokens = (Token *)realloc(ast->tokens, ast->tkSize * sizeof(Token)); ast->tokens[ast->tkSize - 1].type = l_string; ast->tokens[ast->tkSize - 1].value.l_string = scaned; } } }
1. 初始内存分配非法
char *buffer = (char *)malloc(bSize); 中bSize初始值为0,malloc(0)的行为是实现定义的:要么返回NULL,要么返回一块无法用于存储数据的内存区域。无论哪种情况,后续对buffer的读写操作都是非法内存访问,直接触发段错误。
2. realloc的尺寸计算错误
buffer = (char *)realloc(buffer, bSize++); 使用了后置自增运算符,第一次循环时会先以bSize=0的尺寸调用realloc,再将bSize加1——这意味着第一次分配的内存仍然是0字节,完全无法存储字符。
更致命的是:C语言字符串必须以'\0'结尾,你分配的内存从未预留存储终止符的空间,导致strncat无法找到合法的字符串末尾,必然越界访问内存。
3. strncat的使用前提不满足
strncat要求目标缓冲区必须是以'\0'结尾的合法字符串,但你分配的内存未初始化,内部是随机垃圾值,没有'\0'。strncat会从buffer起始位置开始扫描,直到找到'\0'才会追加字符,这个过程会访问未分配的内存区域,直接引发段错误。
修复方向
- 初始分配时至少预留1字节用于存储
'\0',并手动初始化:size_t bSize = 1; char *buffer = malloc(bSize); buffer[0] = '\0'; - 调整
realloc的尺寸:每次新增字符时,分配++bSize的空间(包含终止符),比如buffer = realloc(buffer, ++bSize); - 替换
strncat为直接赋值:利用bSize直接定位缓冲区位置,buffer[bSize-2] = temp; buffer[bSize-1] = '\0';,避免依赖strncat对终止符的要求 - 避免重复计算字符串长度:先将
strlen(program)的结果保存到变量中,再用于循环条件,提升效率
内容的提问来源于stack exchange,提问作者Jason Ghantous
相关产品推荐
相关产品推荐

