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

C++中new分配内存未触发泄漏?原因分析及修改方案

关于C++中new/delete对基本类型的机制与内存泄漏问题

一、new/delete处理基本类型的工作机制

  • new T[N](比如new int[10000]):直接在堆上分配能容纳N个T类型对象的连续内存空间,因为是基本类型,不会调用构造函数;分配成功后返回指向内存起始地址的指针。
  • delete[] ptr:对应数组形式的new操作,直接释放ptr指向的堆内存空间,同样因为是基本类型,不会调用析构函数;注意必须严格用delete[]匹配数组new,虽然基本类型用普通delete可能不会立刻出问题,但属于未定义行为,绝对不能这么做。

二、无智能指针时的自动内存管理?

不存在。C++里如果不用智能指针(std::unique_ptr/std::shared_ptr等)、自动管理内存的容器(比如std::vector)或者RAII类,堆内存完全需要手动管理——你用new/new[]分配的内存,必须自己用delete/delete[]释放,操作系统只会在程序退出时回收进程所有内存,运行期间不会主动帮你清理堆上的分配。

三、为什么你的代码没出现内存占用增长?

你的代码每次调用MemoryLeak(10000)后就丢失了堆内存的指针,理论上已经造成内存泄漏,但看不到内存增长的原因主要有这几点:

  1. 内存分配器的缓存机制:C++的内存分配器(比如glibc的ptmalloc)会把“泄漏”的内存缓存起来,下次分配同大小的内存时优先复用缓存,不会立刻还给操作系统,所以操作系统层面看到的进程内存占用不会持续上升。
  2. 单次分配内存太小:10000个int仅约40KB,现代系统的内存管理对这种小内存块的分配有优化,多次重复分配也很难显现出明显的内存增长。
  3. 系统内存统计的延迟:任务管理器、top这类工具显示的进程内存数值,不会实时精确反映堆内存的实际分配情况,存在统计滞后或合并计算的可能。

四、如何修改代码触发明显的内存泄漏?

可以从两个方向调整:

  1. 增大单次分配的内存量,同时保存所有分配的指针,避免分配器复用内存块:
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>

int* MemoryLeak(const int size) {
    std::cout << "Allocating space for " << size << " ints..." << std::endl;
    return new int[size];
}

int main() {
    std::string keepGoing = "y";
    std::vector<int*> leakedPtrs; // 保存所有分配的指针,让内存无法被复用
    
    while (keepGoing != "n") {       
        std::cout << "Leak memory? [y/n]" << std::endl; 
        
        std::cin >> keepGoing;
        std::transform(keepGoing.begin(), keepGoing.end(), keepGoing.begin(), ::tolower);
        
        if (keepGoing == "y") {
            leakedPtrs.push_back(MemoryLeak(1000000)); // 单次分配约4MB内存
        } else if (keepGoing != "n") {
            keepGoing = "y";
        }
    }
}

运行这段代码,每次输入y都会分配一块新的4MB内存,且指针被容器保存,分配器无法复用之前的内存,你能明显看到进程内存占用持续增长。


内容的提问来源于stack exchange,提问作者fe.dev

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 16:00:51