c++如何测试堆中的某个内存位是否空闲
c++ How to test whether a certain bit of memory in the heap is free?
我有一些代码:
int *ip = new int;
*ip = 42;
cout << *ip << endl;
cout << ip << endl;
delete ip;
cout << *ip << endl;
cout << ip << endl;
输出为:
42
0x100105400
42
0x100105400
从指针的值和它指向的内存上的值,我想我不知道ip
指向的堆中的内存位是否空闲?
我知道,如果在代码之后再次添加delete ip;
,编译器会抛出一个错误。这将是一个很好的证据,证明记忆是自由的。
但是,我如何和平地测试它是否是免费的,以便将其作为决定代码中进一步操作的条件?
如果您的代码取决于特定内存是否可用,那么您可能会遇到一些设计问题。但是,如果您确实想测试,您可以重载operator new
和operator delete
(以及它们相应的数组/类版本),这样它们就可以跟踪在程序可用的某些全局数据结构中分配了哪些内存位置。下面是一些玩具示例(live-on-ideone.com),它定义了一个位置new
,用于跟踪分配了什么内存(和大小)。
#include <iostream>
#include <map>
std::map<void*, std::size_t> memory; // globally allocated memory map
struct tag {}; // tag for placement new's so we don't overload the global ones
void* operator new(std::size_t size, const tag&)
{
void* addr = malloc(size);
memory[addr] = size;
return addr;
}
void* operator new[](std::size_t size, const tag&) // for arrays
{
return operator new(size, tag());
}
void operator delete(void *p) noexcept
{
memory.erase(p);
free(p);
}
void operator delete[](void *p) noexcept // for arrays
{
operator delete(p);
}
void display_memory()
{
std::cout << "Allocated heap memory: " << std::endl;
for (auto && elem : memory)
{
std::cout << "tADDR: " << elem.first << " "
<< "SIZE: " << elem.second << std::endl;
}
}
bool is_allocated(void* p)
{
return (memory.find(p) != memory.end());
}
int main()
{
int *p = new(tag()) int[10];
char *c = new(tag()) char;
// test if p is allocated
std::cout << std::boolalpha << "Allocated: "
<< is_allocated(p) << std::endl;
// display the allocated memory
display_memory();
// remove p
delete[] p;
// test again if p is allocated
std::cout << std::boolalpha << "Allocated: "
<< is_allocated(p) << std::endl;
display_memory();
// remove c
delete c;
display_memory();
}
编辑:我意识到上面的代码可能有一些问题。在功能中
void operator delete(void *p) noexcept
{
memory.erase(p);
free(p);
}
memory.erase(p)
还会调用operator delete
,因此可能会出现一些令人讨厌的递归(出于某种原因,上面的代码只进入一次递归)。修复方法是为使用malloc/free
而不是全局operator new/delete
的std::map memory
编写一个自定义分配器。
但是,我如何和平地测试它是否是免费的,以便将其作为决定代码中进一步操作的条件?
释放内存不会改变指针的值,也不一定会改变它所指向的内存(无论如何,释放内存后都不应该尝试访问)。
您应该做的是在删除它时将指针设置为nullptr
,然后您可以检查它是否为nullptr
,看看它是否已释放。
示例:
int* ip = new int;
*ip = 42;
delete ip;
ip = nullptr;
// ...
if (ip) {
delete ip;
ip = nullptr;
}
为了完整起见,这里有一个链接到Doug Lea的免费商店实现页面:http://g.oswego.edu/dl/html/malloc.html.
在第一个图,即内存布局中,您可以看到每个分配块的用户数据前面都有记账信息,其中包括一个"使用中"标志。组块形成了一个链表:从给定的组块中,可以访问之后的所有组块(实际上,也可以访问之前的组块)。
知道数据大小和对齐要求,就可以在给定的系统上猜测该信息可能相对于返回的指针;在我的x86_64-pc-cygwin上,状态字节是返回地址之前的8个字节,"使用中"标志是第一个字节的2位。
虽然这看起来很有希望,但有一个问题:四处寻找,我可以看到delete()合并了相邻的块,使得记账信息只在融合的块的开头有效:如果你有两个指针p1、p2,它们指向按顺序分配的空闲存储中的内存,然后你再次按顺序删除,在p2的记账位置处的存储器不被刷新以反映p2被解除分配。相反,p1之前的记账区域现在指示下面的内存块具有单个块组合的大小。
为了查明给定指针所指向的内存是否已被释放,必须遍历内存块的链表,大概是从一个先于其他对象分配的虚拟对象开始。当然可能,但不可取,也不稳健@vsoftco的想法要好得多。
最后一点:总是从main返回int的人可能会哀叹这一切都是UB。他们是对的。
- 我在 IDA 或 dbg 或 olly 上看到的内存是否与我在 RAM 上实时加载的内存相同?
- 访问"std::vector"的保留但未调整大小的内存作为原始内存是否安全?
- 本地分配的内存是否可以用于将来使用?
- 多次分配内存是否一次性需要更多时间?
- 删除矢量的尾部(通过擦除)内存是否有效
- 如何找出内存是否属于堆或堆栈
- C++:提升:托管共享内存是否需要信号量锁
- 在 C/C++ 中在特定地址边界上对齐内存是否仍能提高 x86 性能?
- 检查内存是否在堆上
- C++内存 - 是否需要删除使用 'new' 创建的基元类型变量?
- 如果通过委托给“malloc”的重载“new[]”分配,“释放”内存是否安全
- 分配给 cpp 中定义的全局静态变量的内存是否在 C++ 中删除其类的实例后释放
- 我的 265GB RAM 笔记本电脑上的内存是否超过 8GB
- 在动态内存分配中,在程序终止并且忘记释放内存后,该内存是否保持分配状态
- 这些二维数组(C++)的内存是否不足
- 如果我在 for 中声明一个对象,它的内存是否会在那之后被释放?
- 二进制搜索树(如何在插入时检查内存是否不足)
- 用new重新分配内存是否安全
- 在构造函数初始化列表中分配内存是否存在任何问题
- 内存映射内存是否可能