2015-02-23 69 views
4

为什么在delete this;之后的调用堆栈中调用以下函数?删除调用memset?

msvcr110d.dll!_VEC_memset(void * dst, int val, int len) 

请认真考虑operator delete没有超载。

+3

你在调试模式或发布模式? – Brandon 2015-02-23 13:28:42

+5

这是一个调试版吗?如果是这样的话,那就是用已知的位模式填充死锁,以便更容易地查看它是否在删除后使用。在发布版本中,我会担心的。 – 2015-02-23 13:28:46

+0

翻阅一些[MSDN讨论](https://social.msdn.microsoft.com/Forums/en-US/a51fe950-cd74-4133-8d84-1bc07b353bc2/msvc-2005-automatically-calling-memset?forum=Vsexpressvc )它看起来可能是MSVC编译器优化的一部分。如果在项目选项中将“优化”设置为“优化速度”,它应该消失。 – AndyG 2015-02-23 13:30:32

回答

7

在调试版的Microsoft C/C++运行时库中,delete使用memset将释放的内存设置为0xDD。这就是为什么你在调用堆栈中看到memset。你不会在发行版中看到它。
同样地,当存储器是通过new分配,则新分配的存储器被设置为0xCD

你可以看到这里的一些细节 - https://msdn.microsoft.com/en-us/library/974tc9t1.aspx

+0

删除后访问该内存并且在调试模式下没有崩溃应用程序也是正常的吗? – 2015-02-23 13:45:33

+0

@ TM_也可能在发布。删除后访问内存是未定义的行为。任何事情都可能发生,包括伟大的事情或坏事。 – user93353 2015-02-23 13:48:22

+0

我检查了析构'bool'的值是'true(254)',并且析构'int'的值是'-17891602' – 2015-02-23 14:00:46

3

可能是你在调试模式下工作。在这种情况下,如果有人一直在阅读一个释放的块,那么通常会填满释放的区域以尽早发现。

此外,稍后重新使用该块时,可能会检测到某人在删除后是否写入某个区域。

+0

所以删除它后,如果我记得地址,我仍然可以使用该对象? – 2015-02-23 13:47:19

+1

@TM_:NO。删除后请勿使用对象。这是未定义的行为。 – NathanOliver 2015-02-23 13:48:34

+0

@TM_:不,你不能,但它是一个常见的错误做到这一点,这是该库的调试版本填充有特殊图案的内存来加速这种错误检测的原因,如果(例如你的' page_number'突然变成3735928559程序的其余部分希望会早点崩溃)。 – 6502 2015-02-23 13:58:24