简体   繁体   English

struct epoll_event memset 还是没有 memset?

[英]struct epoll_event memset or no memset?

When browsing through code on the Internet, I often see snippets like these:在网上浏览代码时,经常会看到这样的片段:

struct epoll_event event;
memset(&event, 0, sizeof(event));

This pattern seems needless to me, if event is filled out in full, but it is widespread.如果事件被完整填写,这种模式对我来说似乎是不必要的,但它很普遍。 Perhaps to take into account possible future changes of the struct?也许是考虑到结构未来可能发生的变化?

This is surely just bad copy-and-paste coding.这肯定只是糟糕的复制粘贴编码。 The man page for epoll does not document any need to zero-initialize the epoll_event structure, and does not do so in the examples. epoll的手册页没有记录对epoll_event结构进行零初始化的任何需要,并且在示例中也没有这样做。 Future changes to the struct do not even seem to be possible (ABI), but if they were, the contract would clearly be that any parts of the structure not related to the events you requested would be ignored (and not even read, since the caller may be passing a pointer to storage that does not extend past the original definition).未来对结构的更改似乎是不可能的(ABI),但如果是这样,合同显然会是与您请求的events无关的结构的任何部分都将被忽略(甚至不会读取,因为调用者可能正在传递一个指向未超出原始定义的存储的指针)。

Also, in general it's at best pointless and at worst incorrect/nonportable to use memset when a structure is supposed to be zero-initialized, since the zero representation need not be the zero value (for pointer and floating point types).此外,一般来说,当结构应该为零初始化时,使用memset充其量是毫无意义的,最坏的情况是不正确/不可移植,因为零表示不一定是零值(对于指针和浮点类型)。 Nowadays this generality is mostly a historical curiosity, and not relevant to a Linux-specific interface like epoll anyway, but it comes up as well with mbstate_t which exists in fully general C, and where zero initialization is required to correctly use the associated interfaces.如今,这种普遍性主要是历史上的好奇心,无论如何与epoll这样的 Linux 特定接口无关,但它也出现在完全通用的 C 中存在的mbstate_t中,并且需要零初始化才能正确使用相关接口。 The correct way to zero-initialize things that need zero values, rather than all-zero-bytes representations, is with the universal zero initializer, { 0 } .对需要零值而不是全零字节表示的事物进行零初始化的正确方法是使用通用零初始化器{ 0 }

Using memset like this can help you locate bugs faster.像这样使用 memset 可以帮助您更快地定位错误。 Consider it a defensive (even secure) style of programming.将其视为一种防御性(甚至是安全)的编程风格。

Lets say you didn't use memset, and instead attempt to diligently fill in each member as documented by the API.假设您没有使用 memset,而是尝试按照 API 的记录认真填写每个成员。 But if you ever forget to fill in a field (or a later API change leads to the addition of a new field), then the value that field takes at run-time is undefined;但是,如果您忘记填写一个字段(或后来的 API 更改导致添加一个新字段),那么该字段在运行时采用的值是未定义的; and in practice will use whatever the memory previously held.在实践中将使用之前持有的任何 memory。

What are the consequences?后果是什么?

If you are lucky, your code will immediately fail in a nice way that can be debugged, for example, if the unset field needs a highly specific value.如果你很幸运,你的代码会立即以一种可以调试的方式失败,例如,如果未设置的字段需要一个高度特定的值。

If you are unlucky, your code may still work, and it may work for years.如果你不走运,你的代码可能仍然有效,并且可能工作多年。 Perhaps on your current operating system the program memory somehow already held the correct value expected by the API.也许在您当前的操作系统上,程序 memory 不知何故已经保持了 API 期望的正确值。 But as you move your code across systems and compilers, expect confusing behavior: "it works on my machine, but I don't understand why it doesn't work on yours".但是,当您跨系统和编译器移动代码时,会出现令人困惑的行为:“它可以在我的机器上运行,但我不明白为什么它不能在您的机器上运行”。

So in this case, memset is helping you avoid this undeterministic behavior.所以在这种情况下,memset 正在帮助您避免这种不确定的行为。

Of course, you can still profile your code, check for undefined memory, unit tests etc. Doing memset is not a replacement for those.当然,您仍然可以分析您的代码,检查未定义的 memory,单元测试等。执行 memset 并不能替代这些。 It's just another technique to get to safe software.这只是获得安全软件的另一种技术。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM