为何调用free()会导致这段C语言代码程序崩溃?
C语言释放动态分配字符串时崩溃的问题排查与解决
问题核心错误点分析
你的代码里有两个关键问题直接导致了free()调用时崩溃:
1. 内存分配未预留字符串终止符空间
strlen(buffer)返回的是字符串不含末尾\0的字符长度,但C语言字符串必须以\0结尾才能被正确识别。你用realloc(NULL, sizeof(char) * strlen(buffer))分配的空间,刚好只能放下buffer里的字符,没有多余空间存储\0。
当调用strcpy(formattedMessage, buffer)时,strcpy会把buffer里的所有字符包括\0一起复制,这就触发了堆内存越界写入,破坏了堆内存的管理结构。后续调用free()时,堆管理器检测到内存结构异常,直接引发崩溃。
2. 错误的free()调用写法
free()函数的返回值是void,你写的token->lexeme = free((void*)(token->lexeme));完全是错误的逻辑。这种写法不仅毫无意义,还可能在部分环境下引发额外问题。正确的做法是单独调用free(),不需要赋值操作。
修正后的代码示例
typedef struct Token { size_t length; const char* lexeme; // Other members } Token; static char buffer[1024]; // ... 填充buffer的代码 ... // 修正:分配空间时+1,为'\0'预留位置 char* formattedMessage = realloc(NULL, sizeof(char) * (strlen(buffer) + 1)); if (formattedMessage == NULL) { // 新增:内存分配失败的错误处理 perror("realloc failed for formattedMessage"); exit(EXIT_FAILURE); } Token* token = realloc(NULL, sizeof(Token)); if (token == NULL) { // 新增:结构体分配失败时,先释放已分配的字符串内存 free(formattedMessage); perror("realloc failed for token"); exit(EXIT_FAILURE); } token->lexeme = strcpy(formattedMessage, buffer); // 优化:直接用strlen(buffer),避免重复计算字符串长度 token->length = strlen(buffer); // ... 其他业务代码 ... // 正确的释放流程 free((void*)token->lexeme); token->lexeme = NULL; // 可选:置空指针,避免后续误操作野指针 free(token); token = NULL;
额外注意事项
- 所有动态内存分配调用(
realloc/malloc等)必须检查返回值是否为NULL,避免空指针操作。 - 释放结构体时,要先释放内部的动态分配成员(
lexeme指向的内存),再释放结构体本身,顺序不能颠倒。 token->lexeme是const char*,仅限制通过该指针修改内容,不影响释放内存,转成void*调用free()是合法操作。
内容的提问来源于stack exchange,提问作者Mark Edwards
相关产品推荐
相关产品推荐

