Sky*_*leh 27 c c++ null pointers
在各种代码中,我已经看到调试版本中的内存分配NULL...
memset(ptr,NULL,size);
Run Code Online (Sandbox Code Playgroud)
或者0xDEADBEEF......
memset(ptr,0xDEADBEEF,size);
Run Code Online (Sandbox Code Playgroud)
0xDEADBEEF,是否仍然不符合有效数据?AnT*_*AnT 57
使用memset(ptr, NULL, size)或memset(ptr, 0xDEADBEEF, size)清楚地表明作者不理解他们在做什么.
首先,memset(ptr, NULL, size)如果NULL定义为整数零,则确实将C和C++中的内存块清零.
但是,NULL在此上下文中使用表示零值不是可接受的做法.NULL是专门为指针上下文引入的宏.第二个参数memset是整数,而不是指针.将存储器块清零的正确方法是memset(ptr, 0, size).注意:0不是NULL.我会说甚至memset(ptr, '\0', size)看起来都比memset(ptr, NULL, size).
此外,最新的(目前)C++标准--C++ 11 - 允许定义NULL为nullptr.nullptrvalue不能隐式转换为type int,这意味着上述代码无法保证在C++ 11及更高版本中进行编译.
在C语言中(并且您的问题也标记为C)宏NULL可以扩展为(void *) 0.即使在C中(void *) 0也不能隐式转换为类型int,这意味着一般情况下memset(ptr, NULL, size)只是C中的无效代码.
其次,即使第二个参数为memsethas类型int,该函数也将其解释为unsigned char值.这意味着只使用该值的一个低字节来填充目标内存块.由于这个原因memset(ptr, 0xDEADBEEF, size)将编译,但不会用0xDEADBEEF值填充目标内存区域,因为代码的作者可能天真地希望.memset(ptr, 0xDEADBEEF, size)是等价的memset(ptr, 0xEF, size)(假设8位字符).虽然这可能足以用有意的"垃圾"来填充一些记忆区域,但是作者memset(ptr, NULL, size)或者memset(ptr, 0xDEADBEEF, size)仍然背叛了作者的主要缺乏专业性.
同样,正如其他答案已经指出的那样,这里的想法是用"垃圾"值填充未使用的内存.在这种情况下,零肯定不是一个好主意,因为它不够"丰富".使用时,memset您只能使用一个字节的值,例如0xAB或0xEF.如果这对您的目的足够好,请使用memset.如果你想要一个更具表现力和独特的垃圾价值,比如0xDEDABEEF或0xBAADFOOD,你将无法使用memset它.您必须编写一个专用函数,可以用4字节模式填充内存区域.
C和C++中的指针不能被赋予任意整数值(除了空指针常量,即零).只能通过使用显式强制转换将积分值强制转换为指针来实现此类赋值.从形式上讲,这种演员表的结果是实现定义的.结果值当然可以指向有效数据.
650*_*502 10
写入0xDEADBEEF或其他非零位模式是一个好主意,能够捕获写后删除和读后删除使用.
通过编写特定模式,您可以检查已经解除分配的块是否稍后被错误代码写入; 在我们的调试内存管理器中,我们使用一个空闲的块列表,在回收内存块之前,我们检查我们的自定义模式是否仍在整个块中写入.当然,当我们发现问题时,它有点"迟到",但仍然比发现不进行检查时更早.我们还有一个特殊的函数,它被定期调用,也可以按需调用,只需要遍历所有释放的内存块列表并检查它们的一致性,因此我们可以在追逐错误时经常调用此函数.使用0x00000000as值不会那么有效,因为零可能正好是错误代码想要在已经解除分配的块中写入的值,例如将字段置零或将指针设置为NULL(相反,错误的代码更不可能写入0xDEADBEEF).
将解除分配的块的内容保持不变甚至只写零都会增加读取死存储器块内容的人仍然会发现合理的值并与不变量兼容的可能性(例如,许多架构上的NULL指针NULL只是二进制零,或整数0,ASCII NUL字符或双精度值0.0).通过编写"奇怪"模式,如0xDEADBEEF大多数将在读取模式下访问的代码,这些字节可能会找到奇怪的不合理值(例如整数-559038737或双值,值-1.1885959257070704e + 148),希望触发一些其他自我一致性检查断言.
当然没有什么是特定于位模式的0xDEADBEEF,实际上我们对释放的块使用不同的模式,块前区域,块后区域以及我们的内存管理器将另一个(依赖于地址的)特定位模式写入内容部分.将任何内存块提供给应用程序之前(这有助于查找未初始化内存的使用).
我肯定会推荐0xDEADBEEF.它清楚地标识未初始化的变量,并访问未初始化的指针.
奇怪的是,取消引用0xdeadbeef指针肯定会在加载单词时在PowerPC体系结构上崩溃,并且很可能在其他体系结构上崩溃,因为内存很可能在进程的地址空间之外.
归零内存是一种方便,因为许多结构/类具有使用0作为其初始值的成员变量,但我非常建议初始化构造函数中的每个成员而不是使用默认的内存填充.您真的希望了解是否正确初始化变量.
http://en.wikipedia.org/wiki/Hexspeak
这些"神奇"数字是用于识别错误指针,未初始化内存等的调试辅助工具.您需要在正常执行期间不太可能发生的值以及在执行内存转储或检查变量时可见的值.在这方面,初始化为零不太有用.我猜想当你看到人们初始化为零时,这是因为他们需要将该值设置为零.值为0xDEADBEEF的指针可能指向有效的内存位置,因此将其用作NULL的替代方案是一个坏主意.