你啥时候在 C++ 中对一个结构进行 ZeroMemory 处理?
Posted
技术标签:
【中文标题】你啥时候在 C++ 中对一个结构进行 ZeroMemory 处理?【英文标题】:When do you ZeroMemory a struct in C++?你什么时候在 C++ 中对一个结构进行 ZeroMemory 处理? 【发布时间】:2014-04-07 10:52:12 【问题描述】:我见过使用 ZeroMemory 的示例(主要用于 windows 和 directx 结构),但其他时候不使用它。我什么时候应该对结构进行零内存?
【问题讨论】:
【参考方案1】:ZeroMemory
只是用 0 填充结构的内存,这本质上意味着结构的每个值都设置为 0。如果在传递之前没有将结构的所有值设置为自定义值,则这是必要的例如 API 函数。创建结构时,每个字段中都有未指定的值 - 这会导致函数中出现未定义的行为,然后访问结构的字段。
【讨论】:
它们不能被“误解”。即使读取未初始化的值也是导致程序格式错误的未定义行为。 他们可以,因为接收值的函数假定这些值是正确的。它无法检查这些值是否由用户设置,或者它们是否是该内存区域的初始值(可能是任何值)。 您似乎不理解 C 中未初始化的值。访问它们是未定义的行为。你不会得到误解,只是简单的未定义行为。 不,我的意思是任何值,包括指针。阅读***.com/questions/11962457/… 好吧,你是对的 :) (根据该信息编辑问题)【参考方案2】:您几乎不应该在 C++ 中这样做,除非您正在编程的某些外部 API 要求您这样做(这可能适用于旧的 Windows C API)。有一些方法可以使用默认构造函数来初始化数据,这样如果内存中的数据类型发生变化,构造就会自动调整。使用ZeroMemory
初始化数据是脆弱的。
有趣的是,微软提到ZeroMemory
甚至可能无法在this documentation for SecureZeroMemory
中工作:
当您想确保您的数据将被及时覆盖时,请使用此函数而不是
ZeroMemory
,因为某些 C++ 编译器可以通过完全删除对ZeroMemory
的调用来优化它。
【讨论】:
【参考方案3】:如果您正在创建 C++ 程序,请不要使用 ZeroMemory。使用构造函数和初始化列表来初始化字段。顺便说一句,在 C++11 中,您可以使用以下语法:
struct A
int x = 0;
int y = -1;
int z = 42;
;
而不是“旧式”
struct A
int x;
int y;
int z;
A() : x( 0 ), y( -1 ), z( 42 )
;
【讨论】:
【参考方案4】:ZeroMemory(&a, sizeof(a))
等于 memset(&a, 0, sizeof(a));
。它只是用零填充内存。
但您必须注意a
应该是 POD 数据。也就是说,您不得这样做:
std::string str;
ZeroMemory(&a, sizeof(a)); // never!!
您应该使用 ZeroMemory
和 memset
来处理 POD 数据。 (如果您不了解 POD 数据,它就像 C 样式的结构。)如果您对非 POD 执行 memset
,未定义的行为将会出现..
【讨论】:
真正的问题是一个 可以memset
非 POD,但它会产生未定义的行为。它可能有效,也可能无效,但无论如何,它会生成不可移植且高度脆弱的代码。
确实如此。你帖子中的问题,你写了that is, you can't this:
和// error!!
,但你也不能不这样做,也不会产生错误。你完全可以memset
C++ 中的所有内容,但在合法 的基础上,这会产生未定义的行为。
@phresnel 嗯..我打算“你不能这样做;如果你这样做,会发生错误”,但我同意有一些误导。我会编辑。
现在看起来好多了:)【参考方案5】:
当您创建一个结构时(尤其是在使用旧的 Win32 API 遗留代码时),您分配的结构中可能有垃圾,因为这些 Win32 结构没有真正的构造函数。所以这是一种将结构初始化为默认值的方法。
【讨论】:
【参考方案6】:当有很多值要填写并且零是您对手动设置不感兴趣的部分的有效值时,您将结构归零。抱歉,如果这有点含糊,但基本上就是这样(例如,您有一个充满指针的结构,对于可选值,这些指针允许为 NULL
,而您只想设置其中的几个)。
请记住,如果您不将 struct 成员设置为任何内容,在大多数情况下,当您创建它们时,它们会充满垃圾(在 C++ 中,结构可能有一个已经为您处理好这些的构造函数)。
ZeroMemory
虽然是 Windows 的东西,但标准等价物是 memset(ptr,0,size)
。在 C++ 中它不是你经常需要的东西,尽管它在 C 中出现了很多(尽管你也可以在 C 中编写类似函数的构造函数,我建议你这样做)。
【讨论】:
【参考方案7】:它依赖于编译器,新的 gcc 自动将结构归零,但旧的结构具有随机值(根据 maxdev)。
看看这个线程: When zeroing a struct such as sockaddr_in, sockaddr_in6 and addrinfo before use, which is correct: memset, an initializer or either?
【讨论】:
以上是关于你啥时候在 C++ 中对一个结构进行 ZeroMemory 处理?的主要内容,如果未能解决你的问题,请参考以下文章