众所周知,Visual C++运行时标记未初始化或刚刚释放的具有特殊非零标记的内存块.有没有办法完全禁用此行为,而无需手动将所有未初始化的内存设置为零?这是因为我的有效非空检查造成了破坏0xFEEEFEEE != 0
.
嗯,也许我应该更好地解释一下.我创建并初始化一个变量(通过new),一切都很好.当我释放它(通过删除)时,它将指针设置为0xFEEEFEEE
而不是NULL
.当我插入一个适当的检查NULL
,因为所有管理自己的内存的好程序应该,我提出问题,因为0xFEEEFEEE
通过NULL
检查没有问题.有没有什么好的方法,除了NULL
在删除它们时手动设置所有指针,以检测何时已释放内存?我宁愿不使用Boost只是因为我不想要开销,虽然它可能很小,因为这是我唯一使用Boost的东西.
创建指针时,explicity将其初始化为NULL
.同样在一个delete
.取决于未初始化数据的值(除少数特定情况外)是在寻找麻烦.
通过使用智能指针类(例如boost::shared_ptr
)可以自动处理是否初始化指针,可以避免很多麻烦.
VC++的行为不应该导致你可以做的任何有效检查造成严重破坏.如果你看到0xfeeefeee然后你没有写入内存(或已经释放它),所以你不应该从内存中读取.
如果您正在阅读未初始化的内存,那么您的检查肯定不是"有效".内存被释放.它可能已经被用于其他东西.您不能对C/C++中未初始化的内存的内容做任何假设.
Java(和C#,我相信)将保证在使用之前将分配的内存归零,当然垃圾收集会阻止您看到释放的内存.但这不是C堆的属性,它直接暴露内存.
如果您在Release模式而不是Debug模式下构建,则运行时根本不会填充未初始化的内存,但它仍然不会为零.但是,你应该不依赖于这种行为-你应该明确地自己初始化内存memset的(),ZeroMemory(),或SecureZeroMemory(),或设置一个标志的地方,表明该内存尚未初始化.读取未初始化的内存将导致未定义的行为.
delete
重置所有指向对象的指针不是责任NULL
.此外,您不应该更改Windows DEBUG运行时的默认内存填充,您应该使用像boost::shared_ptr<>
指针一样的东西.
也就是说,如果你真的想用脚射击自己,你可以.
您可以使用这样的分配器挂钩更改 Windows DEBUG运行时的默认填充.这只适用于HEAP分配的对象!
int main(int argc,char** arv) { // Call first to register hook _CrtSetAllocHook(&zero_fill); // Do other stuff malloc(100); } int zero_fill(int nAllocType, void* pvData, size_t nSize, int nBlockUse, long lRequest, const unsigned char *szFileName, int nLine ) { /// Very Importaint !! /// infinite recursion if this is removed !! /// _CRT_BLOCK must not do any thing but return TRUE /// even calling printf in the _CRT_BLOCK will cause /// infinite recursion if ( nBlockUse == _CRT_BLOCK ) return( TRUE ); switch(nAllocType) { case _HOOK_ALLOC: case _HOOK_REALLOC: // zero initialize the allocated space. memset(pvData,0,nSize); break; case _HOOK_FREE: break; } return TRUE; }
你说:
我创建并初始化一个变量(通过new),一切都很好.当我释放它(通过删除)时,它将指针设置为0xFEEEFEEE而不是NULL.当我插入一个正确的NULL检查,因为所有管理自己内存的好程序应该,我提出问题,因为0xFEEEFEEE传递NULL检查没有问题.
即使是MSVC的调试堆程序将不会改变的价值指针你删去-你删除不会改变(甚至为NULL)指针的值.听起来你正在访问一个属于你刚刚删除的对象的指针,这是一个简单明了的bug.
我很确定你要做的事情只会掩盖无效的内存访问.您应该发布一段代码来向我们展示实际发生的情况.