C++单进程内new返回的地址是否唯一?delete后能否返回相同地址?
C++堆内存分配地址规则解答
进程内new返回地址的唯一性
对于**处于有效分配状态(未被释放)**的内存块,new返回的内存地址在单个进程范围内具备全局唯一性。
只要你没有对new返回的指针执行delete/delete[]操作释放对应内存,堆分配器不会将同一地址重复分配给其他内存申请请求。同一时间段内,进程虚拟地址空间中不会出现两个同时生效的堆分配指向相同地址,否则属于堆分配器的严重bug,会直接触发未定义行为。
需要注意的是,这种唯一性仅在内存块的有效生命周期内成立,并不代表地址一旦被分配过就永久不会被复用。
释放后内存地址的复用规则
当之前通过new申请的内存被delete正确释放后,后续调用new申请内存时,完全有可能返回和已释放内存完全相同的地址,这是符合C++语言标准的正常行为,也是所有主流堆分配器的常规设计逻辑。
所有主流堆实现(包括glibc的ptmalloc、Windows系统默认堆、tcmalloc、jemalloc等)都会维护已释放内存块的空闲缓存结构(比如空闲链表、线程本地缓存tcache等),当后续申请的内存大小、对齐要求和空闲缓存中的已释放块匹配时,分配器会直接将该块标记为已分配状态返回,不会刻意分配从未使用过的新地址。
你可以通过简单的代码验证这个行为:
#include <iostream> int main() { int* p1 = new int(42); std::cout << "第一次new返回地址: " << p1 << '\n'; delete p1; // 释放p1指向的内存 int* p2 = new int(100); std::cout << "释放后再次new返回地址: " << p2 << '\n'; // 绝大多数常规编译运行环境下,p1和p2的地址值完全相等 delete p2; return 0; }
不要依赖地址是否相同判断内存是否有效,被delete后的指针属于悬空指针,哪怕后续新分配的内存和它地址相同,在重新分配生效前访问悬空指针都会触发未定义行为。
内容的提问来源于stack exchange,提问作者Chandan Srivastava
相关产品推荐
相关产品推荐

