Undefined behavior – это все, что явно не указано в документации
Jun 30, 2008 · CommentsДокументацияПрограммирование
Навеяно постом про ExUuidCreate и в частности вот этой фразой:
Well, I suggest MSFT to documented this behavior, or at least explain this case in documentation.
Вкратце, суть статьи сводится к тому, что функция ExUuidCreate может изменять содержимое возвращаемого буфера даже в том случае, если она возвращает ошибку. Далее, в комментариях, завязался спор на тему имеет ли функция право трогать буфер в случае ошибки.
Для начала небольшое объяснение почему эта функция имеет право делать с буфером всё что угодно. ExUuidCreate объявлена следующим образом:
NTSTATUS
ExUuidCreate(
OUT UUID *Uuid,
);
Т.е. она пишет сгенерированный GUID в буфер, выделенный вызывающей стороной. Тут важно, что параметр объявлен как “OUT” параметр. Посмотрим, что говорит документация:
__out: The function will only write to the buffer. If used on the return value or with _deref, the function will provide the buffer and initialize it. Otherwise, the caller must provide the buffer, and the function will initialize it.
__out (это тоже самое, что и OUT), указывает на то, что:
-
Вызываемая функция будет только писать в буфер;
-
Вызывающая сторона отвечает за выделение буфера.
Ни слова о состоянии буфера в случае успешного или неуспешного вызова. Но, состояние буфера в случае успешного выполнения описано в документации на саму функцию:
Uuid: Pointer to a caller-allocated UUID (GUID) structure that is set to a new UUID value.
Далее нам понадобиться немного дедукции. Фактически у нас осталось два случая:
-
Функция возвращает ошибку, содержимое буфера не изменилось;
-
Функция возвращает ошибку, содержимое буфера изменилось.
Если считать, что функция не должна изменять содержимое буфера в случае ошибки, то где-то в документации должно быть соответствующее требование. Однако же, такого требования там нет, соответственно правомочны оба варианта. Вывод - состояние “OUT” параметра неопределенно в случае неуспешного вызова.
Какой из этого следует вывод? Мне кажется, он достаточно очевиден: всё, что явно не описано в документации - не определено. В свете этого, можно определить критерии полноты документации: документация полна, если все задуманные аспекты поведения функции (модуля, класса и т.д.) описаны. Если документация описывает детали конкретной реализации, то такая документация избыточна и несколько вредна, так как усложняет внесение изменений в код в будущем.