0xDEADBEEF 与 NULL
在各种代码中,我已经看到调试版本中的内存分配带有 NULL
...
Throughout various code, I have seen memory allocation in debug builds with NULL
...
memset(ptr,NULL,size);
或者使用 0xDEADBEEF
...
memset(ptr,0xDEADBEEF,size);
- 使用每种方法的优点是什么,在 C/C++ 中实现这一点的一般首选方法是什么?
- 如果一个指针被分配了
0xDEADBEEF
的值,它是否仍然服从有效数据?
- What are the advantages to using each one, and what is the generally preferred way to achieve this in C/C++?
- If a pointer was assigned a value of
0xDEADBEEF
, couldn't it still deference to valid data?
推荐答案
使用
memset(ptr, NULL, size)
或memset(ptr, 0xDEADBEEF, size)
清楚地表明了作者这样做的事实不明白他们在做什么.
Using either
memset(ptr, NULL, size)
ormemset(ptr, 0xDEADBEEF, size)
is a clear indication of the fact that the author did not understand what they were doing.
首先,如果 NULL
定义为整数零,memset(ptr, NULL, size)
确实会将 C 和 C++ 中的内存块清零.
Firstly, memset(ptr, NULL, size)
will indeed zero-out a memory block in C and C++ if NULL
is defined as an integral zero.
然而,在此上下文中使用 NULL
表示零值是不可接受的做法.NULL
是一个专门为指针上下文引入的宏.memset
的第二个参数是一个整数,而不是一个指针.将内存块清零的正确方法是 memset(ptr, 0, size)
.注意:0
不是 NULL
.我会说即使 memset(ptr, '', size)
看起来也比 memset(ptr, NULL, size)
好.
However, using NULL
to represent the zero value in this context is not an acceptable practice. NULL
is a macro introduced specifically for pointer contexts. The second parameter of memset
is an integer, not a pointer. The proper way to zero-out a memory block would be memset(ptr, 0, size)
. Note: 0
not NULL
. I'd say that even memset(ptr, '', size)
looks better than memset(ptr, NULL, size)
.
此外,最新的(目前)C++ 标准 - C++11 - 允许将 NULL
定义为 nullptr
.nullptr
value 不能隐式转换为 int
类型,这意味着上面的代码不能保证在 C++11 及更高版本中编译.
Moreover, the most recent (at the moment) C++ standard - C++11 - allows defining NULL
as nullptr
. nullptr
value is not implicitly convertible to type int
, which means that the above code is not guaranteed to compile in C++11 and later.
在 C 语言中(你的问题也被标记为 C)宏 NULL
可以扩展为 (void *) 0
.即使在 C 中 (void *) 0
也不能隐式转换为 int
类型,这意味着在一般情况下 memset(ptr, NULL, size)
只是 C 中的无效代码.
In C language (and your question is tagged C as well) macro NULL
can expand to (void *) 0
. Even in C (void *) 0
is not implicitly convertible to type int
, which means that in general case memset(ptr, NULL, size)
is simply invalid code in C.
其次,即使 memset
的第二个参数的类型为 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)
仍然暴露出作者缺乏专业精神.
Secondly, even though the second parameter of memset
has type int
, the function interprets it as an unsigned char
value. It means that only one lower byte of the value is used to fill the destination memory block. For this reason memset(ptr, 0xDEADBEEF, size)
will compile, but will not fill the target memory region with 0xDEADBEEF
values, as the author of the code probably naively hoped. memset(ptr, 0xDEADBEEF, size)
is eqivalent to memset(ptr, 0xEF, size)
(assuming 8-bit chars). While this is probably good enough to fill some memory region with intentional "garbage", things like memset(ptr, NULL, size)
or memset(ptr, 0xDEADBEEF, size)
still betray the major lack of professionalism on the author's part.
同样,正如其他答案已经指出的那样,这里的想法是用垃圾"值填充未使用的内存.在这种情况下,零肯定不是一个好主意,因为它不够垃圾".使用 memset
时,您只能使用一字节值,例如 0xAB
或 0xEF
.如果这足以满足您的目的,请使用 memset
.如果您想要一个更具表现力和独特的垃圾值,例如 0xDEDABEEF
或 0xBAADFOOD
,您将无法将 memset
与它一起使用.您必须编写一个可以用 4 字节模式填充内存区域的专用函数.
Again, as other answer have already noted, the idea here is to fill the unused memory with a "garbage" value. Zero is certainly not a good idea in this case, since it is not "garbagy" enough. When using memset
you are limited to one-byte values, like 0xAB
or 0xEF
. If this is good enough for your purposes, use memset
. If you want a more expressive and unique garbage value, like 0xDEDABEEF
or 0xBAADFOOD
, you won't be able to use memset
with it. You'll have to write a dedicated function that can fill memory region with 4-byte pattern.
C 和 C++ 中的指针不能分配任意整数值(空指针常量除外,即零).这种分配只能通过使用显式强制转换将整数值强制转换为指针来实现.正式地说,这种类型转换的结果是实现定义的.结果值当然可以指向有效数据.
A pointer in C and C++ cannot be assigned an arbitrary integer value (other than a Null Pointer Constant, i.e. zero). Such assignment can only be achieved by forcing the integral value into the pointer with an explicit cast. Formally speaking, the result of such a cast is implementation defined. The resultant value can certainly point to valid data.
相关文章