在浏览Internet上的代码时,我经常看到这样的代码片段:
struct epoll_event event;
memset(&event, 0, sizeof(event));如果事件是完整填写的,这种模式对我来说似乎是不必要的,但它很普遍。也许是为了考虑到结构未来可能的变化?
发布于 2019-11-08 23:26:41
这肯定是糟糕的复制粘贴编码。The man page for epoll没有记录任何需要对epoll_event结构进行零初始化的需求,在示例中也没有这样做。将来似乎不可能对结构进行更改(ABI),但如果更改了,合同中与您所请求的events无关的任何结构部分都将被忽略(甚至不会被读取,因为调用者可能会传递一个指向存储的指针,该指针不会超出原始定义的范围)。
此外,一般来说,当一个结构应该是零初始化的时候,使用memset在最好的情况下是没有意义的,在最坏的情况下是不正确的/不可移植的,因为零表示不需要是零值(对于指针和浮点类型)。如今,这种通用性主要是历史上的好奇,与epoll这样的Linux特定接口无关,但它也出现在mbstate_t中,它以完全通用的C语言存在,并且需要零初始化才能正确使用相关接口。对需要零值而不是全零字节表示的事物进行零初始化的正确方法是使用通用的零初始化器{ 0 }。
发布于 2019-11-08 23:54:07
像这样使用memset可以帮助您更快地定位bug。把它当作一种防御性的(甚至是安全的)编程风格。
假设您没有使用memset,而是尝试按照API所记录的那样努力地填充每个成员。但是,如果您曾经忘记填充一个字段(或者后来的API更改导致添加了一个新字段),那么该字段在运行时采用的值是未定义的;实际上,它将使用以前保存的任何内存。
后果是什么?
如果您幸运的话,您的代码将立即以一种可以调试的方式失败,例如,如果unset字段需要一个高度特定的值。
如果您不走运,您的代码可能仍然可以工作,而且可能会工作数年。也许在您当前的操作系统上,程序内存已经以某种方式保存了API所期望的正确值。但是,当您在系统和编译器之间移动代码时,可能会出现令人困惑的行为:“它可以在我的机器上运行,但我不明白为什么它不能在您的机器上运行”。
因此,在这种情况下,memset可以帮助您避免这种不确定的行为。
当然,你仍然可以分析你的代码,检查未定义的内存,单元测试等等。这只是获得安全软件的另一种技术。
https://stackoverflow.com/questions/58769291
复制相似问题