Должны ли программы проверять ошибки в функциях WinAPI, которые «не должны», но могут и не работать? - PullRequest
8 голосов
/ 04 апреля 2011

Недавно я обновлял некоторый код, используемый для создания снимков экрана, используя GetWindowDC -> CreateCompatibleDC -> CreateCompatibleBitmap -> SelectObject -> BitBlt -> GetDIBits серии WinAPI-функций.Теперь я проверяю все эти ошибки, потому что они могут, а иногда и терпят неудачу.Но затем я должен выполнить очистку, удалив созданное растровое изображение, удалив созданный DC, и освободив окно DC.В любом примере, который я видел - даже в MSDN - связанные функции (DeleteObject, DeleteDC могут потерпеть неудачу.

Это только один примечательный пример, поскольку все вызовы расположены рядом друг с другом.Но иногда есть другие функции, которые могут давать сбой, но на практике никогда не работают.Такие как GetCursorPos.Или функции, которые могут давать сбой, только если переданы недопустимые данные, такие как FileTimeToSytemTime.

Итак, является ли хорошей практикой проверка ВСЕХ функций, которые могут выйти из строя из-за сбоя?Или все в порядке, чтобы не проверить?И, как следствие, при проверке этих функций, которые должны работать без сбоев, что является правильным?Выдает исключение во время выполнения, используя assert, что-то еще?

Ответы [ 7 ]

5 голосов
/ 04 апреля 2011

Вопрос о том, тестировать или нет, зависит от того, что вы будете делать в случае неудачи.Большинство примеров завершается после завершения очистки, поэтому проверка правильности очистки не имеет смысла, в любом случае программа завершает работу.

Не проверка чего-то вроде GetCursorPos может привести к ошибкам, но в зависимости от кода, необходимого дляизбежать этого определяет, стоит ли вам проверять или нет.Если проверка добавит 3 строки вокруг всех ваших звонков, то, скорее всего, вам лучше пойти на риск.Однако, если у вас есть настройка макроса для его обработки, то добавить этот макрос на всякий случай не помешает. Проверка

FileTimeToSystemTime зависит от того, что вы передаете в него.Время файла из системы?вероятно, безопасно игнорировать это.Пользовательская строка, созданная из пользовательского ввода?наверное, лучше убедиться.

4 голосов
/ 04 апреля 2011

Да. Никогда не знаешь, когда обещанный сервис удивит, если не будет работать. Лучше всего сообщить об ошибке даже для неожиданностей. В противном случае вы окажетесь с клиентом, который скажет, что ваше приложение не работает, и причина будет полной загадкой; вы не сможете своевременно и полезно ответить вашему клиенту, и вы оба проиграете.

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

3 голосов
/ 04 апреля 2011

Забавно, что вы упоминаете GetCursorPos, поскольку он не работает на процессах Wow64, когда переданный адрес> 2 ГБ. Это терпит неудачу каждый раз. Ошибка была исправлена ​​в Windows 7.

Так что, да, я думаю, что стоит проверять ошибки, даже если вы их не ожидаете.

2 голосов
/ 04 апреля 2011

Да, вам нужно проверить, но если вы используете C ++, вы можете воспользоваться RAII и оставить очистку для различных ресурсов, которые вы используете.

Альтернативой может быть перемешивание операторов if-else, и это действительно уродливо и подвержено ошибкам.

1 голос
/ 26 июня 2018

Чем дольше я кодирую с WinAPI с C ++ и в меньшей степени с PInvoke и C #, тем больше я проделываю это следующим образом:

  1. Проектируйте использование так, чтобы предполагать, что оно потерпит неудачу (в конце концов), независимо от того, что документация подразумевает
  2. Удостоверьтесь, что знаете значение возвращаемого значения для pass / fail, так как иногда 0 означает проход, и наоборот
  3. Проверьте, отмечено ли GetLastError, и определите, какое значение эта информация может придать вашему приложению

Если надежность является достаточно серьезной целью, вы можете посчитать ее достойным вложением времени, чтобы посмотреть, сможете ли вы создать отказоустойчивый дизайн с избыточными средствами, чтобы получить все, что вам нужно. Во многих случаях с WinAPI есть несколько способов получить нужную информацию или функциональность, которые вы ищете, а иногда это означает использование других библиотек / сред Windows, которые работают в сочетании с WinAPI.

Например, получение экранных данных может быть выполнено с помощью прямых WinAPI, но популярной альтернативой является использование GDI +, который хорошо работает с WinAPI.

1 голос
/ 04 апреля 2011

Да.Если функция может выйти из строя, тогда вы должны защитить от нее.

Один из полезных способов классификации потенциальных проблем в коде - это возможные причины сбоя:

  1. недопустимые операции в вашем коде
  2. недопустимые операции в клиентском коде (код, который вызывает ваш, написанный кем-то другим)
  3. внешние зависимости (файловая система, сетевое соединение и т. Д.))

В ситуации 1 достаточно обнаружить ошибку и не выполнять восстановление, поскольку это ошибка, которую вы должны исправить.

В ситуации 2 ошибкаследует уведомить клиентский код (например, с помощью исключения).

В ситуации 3 ваш код должен восстанавливаться, насколько это возможно, автоматически и уведомлять любой клиентский код при необходимости.

В обоих случаяхВ ситуациях 2 и 3 вы должны стремиться к тому, чтобы ваш код восстанавливался до действительного состояния, например, вы должны попытаться предложить «гарантия сильного исключения» и т. д.

1 голос
/ 04 апреля 2011

Да.Предположим, вы не проверяете, что вернула функция, и программа просто продолжает работу после сбоя функции.Что происходит дальше?Как вы узнаете, почему ваша программа долго ведет себя плохо?

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...