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

删除unordered_map元素是否会释放对应malloc分配的内存?

核心结论

你观察到的所有现象都和unordered_map的元素删除逻辑无关,本质是代码存在两处基础的C++内存管理错误,触发了未定义行为,你的初始认知“unordered_map不会自动释放指针指向的malloc内存”是完全正确的。

首先纠正对示例代码的前提误解

你给出的代码里从来没有执行过unordered_map的元素删除操作:既没有调用erase移除键值对,也没有销毁容器本身,容器内从unsigned到sdata*的三个映射始终存在。你做的操作只是读出容器里存的指针值,手动对指针指向的内存做了释放,和容器的元素删除逻辑没有任何关系。

错误1:malloc分配的内存不能用delete释放

C++的内存分配释放是严格配对的,交叉调用会直接触发未定义行为:

  • malloc/calloc/realloc 分配的内存必须用free释放
  • new分配的单个对象必须用delete释放
  • new[]分配的对象数组必须用delete[]释放
    你的代码里所有sdata内存都是通过malloc分配的,却调用了delete去释放,本身就是非法操作。
    另外明确容器的原生内存行为:当unordered_map存储裸指针作为value时,不管是erase删除元素,还是容器自身销毁,都只会释放指针本身占用的内存(32位系统4字节、64位系统8字节),绝对不会自动释放指针指向的堆内存,这部分内存需要手动管理。

错误2:内存释放后继续访问属于野指针操作

你把ht[1]赋值给temp后,两个指针指向同一块堆内存:

  1. 不管你是用配对正确的free还是错误的delete释放了这块内存,这块内存都会被内存管理器标记为“空闲可复用”,原来存储的sdata字段值随时可能被覆写,这时候读取temp->start拿到垃圾值是野指针访问的典型表现。
  2. 你提到释放内存后给temp->start赋值100,再读取能拿到正确值,这也是未定义行为的正常表现:内存被释放不代表对应的内存地址立刻失效、被系统回收,多数内存分配器只是把这块内存挂回空闲链表,短时间内地址依然可读写,写入的值自然能读回来,但这种操作完全非法——这块内存随时可能被分配给其他代码使用,你的写入会篡改其他逻辑的数据,直接引发崩溃或者不可预期的逻辑错误。

正确写法参考

如果要手动管理指针内存,必须保证分配释放配对,且释放内存后禁止再访问对应地址:

struct sdata{
    unsigned pid;
    unsigned long start;
    unsigned long end;
};

int main(){
    std::unordered_map<unsigned,struct sdata*> ht;
    // 方案1:统一用new/delete配对
    ht[0] = new sdata();
    ht[1] = new sdata();
    ht[2] = new sdata();

    // 方案2:统一用malloc/free配对,不要和new/delete混用
    // ht[0] = (struct sdata*)malloc(sizeof(struct sdata));
    // ht[1] = (struct sdata*)malloc(sizeof(struct sdata));
    // ht[2] = (struct sdata*)malloc(sizeof(struct sdata));

    for (int i=0; i< 3; i++){
         ht[i]->start = i;
         ht[i]->end = i+1;
    }
    struct sdata *temp = ht[1];
    // 对应分配方式选释放函数:new配delete,malloc配free
    delete ht[1]; 
    // 释放后立刻把野指针置空,避免误访问
    ht[1] = nullptr;
    temp = nullptr;

    // 后续如果要删除容器元素,直接调用erase即可,注意erase前要确认对应指针指向的内存已经被释放,否则会内存泄漏
    ht.erase(1);
    return 0;
}

实际开发中不推荐在容器里存裸指针管理堆对象,优先使用std::unique_ptr<sdata>、std::shared_ptr<sdata>这类智能指针作为value,容器erase元素或者自身销毁时,会自动调用对应逻辑释放指向的内存,从根源避免内存泄漏、野指针问题。

内容的提问来源于stack exchange,提问作者Arun Kp

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 00:54:26