You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何调用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 19:22:29