如何用free释放malloc分配的堆内存?分词器内存释放异常求助
关于malloc内存释放与分词器deallocate异常的解决方案
一、如何用free释放malloc分配的堆内存
首先,malloc是C标准库中用于在堆内存上分配指定大小空间的函数,返回指向该空间的指针;而free则是唯一用来释放malloc(包括calloc、realloc)分配的堆内存的函数,核心用法很简单:
- 当你通过
char* buf = malloc(100 * sizeof(char));这类代码分配内存后,在不再需要这块内存时,直接调用free(buf);即可释放 - 关键注意事项:
- 不能重复释放同一块内存(比如连续两次
free(buf)),这会触发未定义行为 - 不能释放栈上的内存(比如
int a; free(&a);),同样会导致异常 - 释放后最好将指针置为
NULL,避免后续误操作野指针:buf = NULL;
- 不能重复释放同一块内存(比如连续两次
二、你的分词器deallocate函数异常的原因与修复
先看你的代码,这里存在两个致命问题导致释放内存时行为异常:
1. 错误释放未分配的野指针
在tokenize函数中,你为ret[count]设置了id = TERMINAL,但从未为它的value成员分配内存——也就是说ret[count].value是一个野指针。而你的deallocate函数逻辑是先释放当前i对应的value,再自增i检查是否为TERMINAL,这就导致当i走到count时,会尝试释放这个未分配的野指针,直接触发异常。
2. tokenize函数中的内存越界问题
在处理数字操作数时,你有一行代码:
ret[ret_ind].value = malloc(size * sizeof(char) + 1); ret[ret_ind].value[size + 1] = '\0';
这里malloc分配了size+1个char的空间,合法索引范围是0到size,但你给size+1的位置赋值\0,属于内存越界写入,会破坏堆结构,进而可能导致后续free时出现异常。
修复后的代码
修复deallocate函数
调整循环逻辑,先检查当前token是否为TERMINAL,再决定是否释放:
void deallocate(token *in) { if (in == NULL) { // 先判断指针是否为空,避免空指针访问 return; } int i = 0; while (in[i].id != TERMINAL) { // 先检查当前token是不是TERMINAL,不是才释放 free(in[i].value); i++; } free(in); }
修复tokenize中的越界问题
把字符串结束符的赋值改为正确的索引:
ret[ret_ind].value = malloc(size * sizeof(char) + 1); ret[ret_ind].value[size] = '\0'; // 从size+1改为size,避免越界
额外的健壮性建议
- 在
tokenize函数开头初始化ret = NULL;,避免返回未初始化的野指针(当前代码中如果count == 0,ret是未初始化的) - 在
token_count函数遇到非法字符返回0前,可添加错误提示,方便调试 - 释放内存后,建议将相关指针置为
NULL(比如in[i].value = NULL;),避免野指针问题
内容的提问来源于stack exchange,提问作者KeatonB




