是否可以将C ++中已删除对象的内存清零?我想这样做是为了在单元测试中重现一个coredump:
//Some member variable of object-b is passed-by-pointer to object-a
//When object-b is deleted, that member variable is also deleted
//In my unit test code, I want to reproduce this
//even if I explicitly call delete on object-b
//accessBMemberVariable should coredump, but it doesn't
//I'm assuming even though object-b is deleted, it's still intact in memory
A *a = new A();
{
B *b = new B(a);
delete b;
}
a->accessBMemberVariable();
答案 0 :(得分:20)
您可能应该覆盖delete
运算符。
给定B类的例子:
class B
{
public:
// your code
...
// override delete
void operator delete(void * p, size_t s)
{
::memset(p, 0, s);
::operator delete(p, s);
}
};
编辑:感谢 litb 指出这一点。
答案 1 :(得分:3)
不,为什么要这样? b以前占用的内存很可能现在归CRT所有,CRT是应用程序拥有的CRT。 CRT可以选择不将内存释放回操作系统。只有在访问应用程序拥有的内存而非时,才会发生核心转储。accessBMemberVariable应该是coredump,但它不是
将b占用的内存归零可能对你有任何好处,具体取决于A具有地址的变量类型。
我的建议是在堆叠上分配B,这应该能够带出烟花......但是再一次,不是你期望的那种......
因此,如果你真的想要一个核心转储,你应该使用OS函数分配内存并释放它:
char *buf = OS_Alloc(sizeof(B));
B *b = new(buf) B();
a->someBMember = &b->myMember;
b->~B();
OS_Free(buf);
a->accessBMemberVariable();
答案 2 :(得分:2)
另一张海报建议:
delete b;
memset(b,0,sizeof(B));
请不要这样做!!!对返回到内存管理器的地址空间的写入是UNDEFINED !!!!
即使您的编译器和库让您现在就可以使用它,也不错。库或平台的更改,甚至是编译器中的更新都会让你感到厌烦。
考虑一个竞争条件,你删除b,然后一些其他线程进行分配,b的内存被给出,然后你调用memset!砰,你死了。
如果您必须清除内存(关心的人),请在调用delete之前将其清零。
memset(b,0,sizeof(B));
delete b;
答案 3 :(得分:2)
如果可以,请使用展示位置“new”(http://www.parashift.com/c++-faq-lite/dtors.html#faq-11.10) 并且在手动调用对象析构函数后将你给出的块清零。
答案 4 :(得分:1)
使用环境中的调试malloc / new功能。
在MSVC上,链接调试运行时库。在FreeBSD上,根据需要将MALLOC_OPTIONS设置为具有“Z”或“J”标志。在其他平台上,阅读文档或在具有调试支持的适当分配器中替换。
删除后调用memset()在很多级别上都是坏的。
答案 5 :(得分:0)
在你的例子中写下
'A-> accessBMemberVariable'这是一个错字?不应该是'a-> accessBMemberVariable'?
假设这是一个错字(否则整个设计看起来有点奇怪)。
如果你想验证'a'是否被正确删除,那么改为处理分配的方式并改为使用auto_ptr可能更好。这样你就可以确保删除的东西正确删除了:
auto_ptr<A> a( new A );
{
auto_ptr<B> b( new B(a) ); // B takes ownership of 'a', delete at scope exit
}
a->accessBMemberVariable(); // shouldn't do to well.
和
形式的B的构造函数B( auto_ptr<A>& a ) : m_a(a) {;}
其中
auto_ptr<A> m_a
答案 6 :(得分:-3)
删除b
后,您实际上没有权限写过它的位置。但是你通常可以做到这一点;并且你会看到代码使用memset
的代码。
但是,批准的方法是直接调用析构函数,然后在内存上写入(例如memset
),然后在对象上调用delete
。这确实需要你的析构函数非常聪明,因为delete
将调用析构函数。所以析构函数必须意识到整个对象只不过是0
而没有做任何事情:
b->~B();
memset(b, 0, sizeof(b));
delete b;