struct epoll_event memset или нет memset? - PullRequest
2 голосов
/ 08 ноября 2019

При просмотре кода в Интернете я часто вижу такие фрагменты:

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

Этот шаблон кажется мне ненужным, если событие заполнено полностью, но оно широко распространено. Возможно, принять во внимание возможные будущие изменения структуры?

Ответы [ 2 ]

1 голос
/ 08 ноября 2019

Использование memset, подобного этому, поможет вам быстрее находить ошибки. Считайте это защитным (даже безопасным) стилем программирования.

Допустим, вы не использовали memset, а вместо этого пытаетесь усердно заполнить каждый элемент, как описано в API. Но если вы когда-нибудь забудете заполнить поле (или более позднее изменение API приведет к добавлению нового поля), то значение, которое поле принимает во время выполнения, не определено;и на практике будет использовать любую ранее сохраненную память.

Каковы последствия?

Если вам повезет, ваш код сразу же выйдет из строя приятным способом, который можно отладить, например, если для неустановленного поля требуется очень конкретное значение.

Если вам не повезло, вашкод все еще может работать, и он может работать годами. Возможно, в вашей текущей операционной системе программная память каким-то образом уже содержит правильное значение, ожидаемое API. Но когда вы перемещаете свой код между системами и компиляторами, ожидайте запутанного поведения: «он работает на моей машине, но я не понимаю, почему он не работает на вашей».

Так что в этом случае memset помогает вам избежать этого недетерминированного поведения.

Конечно, вы все равно можете профилировать свой код, проверять наличие неопределенной памяти, юнит-тесты и т. Д. Выполнение memset не являетсязамена для тех. Это просто еще один способ добраться до безопасного программного обеспечения.

1 голос
/ 08 ноября 2019

Это, безусловно, просто плохое копирование и вставка кода. Страница man для epoll не документирует необходимость инициализации нуля структуры epoll_event и не делает этого в примерах. Будущие изменения в структуре даже не кажутся возможными (ABI), но если бы они были, контракт, несомненно, заключался бы в том, что любые части структуры, не относящиеся к запрошенному вами events, будут игнорироваться (и даже не читаться,поскольку вызывающая сторона может передавать указатель на хранилище, которое не выходит за пределы исходного определения).

Кроме того, в общем случае в лучшем случае бессмысленно, а в худшем - некорректно / непереносимо использовать memset, когда предполагается структурабыть инициализированными нулями, поскольку нулевое представление не должно быть нулевым значением (для указателей и типов с плавающей запятой). В настоящее время эта общность в основном является историческим курьезом и не относится к специфическому для Linux интерфейсу, такому как epoll, в любом случае, но она также подходит к mbstate_t, который существует в полностью общем C, и где для правильного использования требуется нулевая инициализациясвязанные интерфейсы. Правильный способ инициализации нуля вещей, которые нуждаются в нулевых значениях, а не в представлениях с нулевыми байтами, заключается в универсальном инициализаторе нуля, { 0 }.

...