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

delete[]是否依赖指针原始指向?下述代码是否合法或存在内存泄漏?

关于delete[]如何知晓数组大小及指针移动后的delete[]有效性问题

一、delete[]是怎么知道要操作的数组大小的?

先从底层内存分配的逻辑说起:

  • 对于malloc和free:malloc在分配内存时,会在内存块的隐藏头部区域记录这块内存的总大小,free就是靠读取这个值来确定要释放的内存范围。
  • 而new[]和delete[]的机制更特殊:它们底层确实依赖malloc/free,但new[]会额外在内存块中单独存储创建的元素数量(这个信息和malloc记录的总内存大小是分开的)。当调用delete[]时,它会先读取这个元素计数:
    • 如果元素类型有自定义析构函数,就按照计数调用对应次数的析构函数;
    • 最后再调用free释放整个内存块。

二、你的代码是否合法?会导致内存泄漏吗?

先看你提供的代码:

void createArray(){
 char* someArray = new char[20];
 readData(someArray);
 //指针移动一位后,此delete是否仍有效?
 delete[] someArray;
}
char readData(char* &arr){
 char value = *arr;
 //让指针指向下一个元素
 arr += 1;
 return value;
}

结论很明确:这段代码属于未定义行为,存在严重风险,绝对不能这么写!

关键原因在于:delete[]有严格的要求——传入的指针必须是**new[]返回的原始起始指针**(或者nullptr)。你的代码里,readData通过引用修改了someArray,让它指向数组的第二个元素,此时传给delete[]的已经不是最初分配的内存起始地址了。

可能你会发现某些环境下这么写程序没崩溃,这是因为char是内置类型,没有析构函数,此时delete[]的行为近似于free。但即使是free,C标准也明确要求传入的指针必须是malloc(或同类分配函数)返回的原始指针,把指向内存块中间的指针传给free同样是未定义行为——它可能在某些系统下“看似正常”,但也可能造成堆损坏、内存泄漏甚至程序崩溃。

正确的做法是始终保留new[]返回的原始指针,用它来调用delete[]。比如可以修改代码,用一个临时指针来遍历数组,不改动原始指针:

void createArray(){
 char* someArray = new char[20];
 char* currentPtr = someArray;
 readData(currentPtr);
 delete[] someArray; // 用原始指针释放,安全合法
}
char readData(char* &arr){
 char value = *arr;
 arr += 1;
 return value;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:38:15