You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何用free释放malloc分配的堆内存?分词器内存释放异常求助

关于malloc内存释放与分词器deallocate异常的解决方案

一、如何用free释放malloc分配的堆内存

首先,malloc是C标准库中用于在堆内存上分配指定大小空间的函数,返回指向该空间的指针;而free则是唯一用来释放malloc(包括callocrealloc)分配的堆内存的函数,核心用法很简单:

  • 当你通过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的空间,合法索引范围是0size,但你给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

火山引擎 最新活动