Могу ли я поставить try / catch вокруг OS API, который вылетает? - PullRequest
0 голосов
/ 11 ноября 2009

Я использую библиотеку ОС Windows для работы с файлами изображений. Иногда он падает глубоко внутри него без видимой причины - все входные данные являются разумными, и это не проблема потоков. Вылет памяти A / V.

Итак, каковы недостатки этого:

try {
  pFoo = OsAPIThatCrashes();
} catch {
  pFoo = NULL;
}

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

Ответы [ 6 ]

4 голосов
/ 11 ноября 2009

С одной стороны, хотя всем нам нравится разбивать MS на недостатки в их программном обеспечении, в IME в 99 случаях из 100 проблема заключалась не в ошибке ОС, компилятора или стандартной библиотеки, а в коде. называя это Какой бы Win API вы ни использовали - он тестируется намного тщательнее, чем большинство (если не весь) код, когда-либо использовавший его.

Далее, try / catch перехватывает исключения C ++, а не исключения ОС. (Более ранние версии VC делали это неправильно, но более поздние версии имеют правильное значение по умолчанию.) Так что try / catch не поймает AV. Тем не менее, VC предоставляет способы ловить исключения ОС. Я думаю, что это называется структурированной обработкой исключений и сосредоточено вокруг __try / __catch, но я не уверен, так как никогда не использовал его. Однако:

Как только ваше приложение столкнулось с AV, все ставки выключены. AV - это всего лишь один из способов проявить себя неопределенным поведением, и как только вы (или код API, каким бы маловероятным он ни был) вызывали неопределенное поведение, вы ничего не можете предположить о состоянии вашего приложения. Вы не должны продолжать.

Подводя итог: вы должны попытаться выяснить, что вы сделали не так. Хороший способ сделать это - попытаться свести проблему к небольшому фрагменту примера кода, который воспроизводит проблему. В 90% всех случаев это выявит ошибку. Если хотя бы небольшой фрагмент кода воспроизвел проблему, а вы до сих пор не знаете, в чем проблема, у вас есть хороший случай для повторного воспроизведения (или для поддержки MS). IME, в 9 из этих 10% кто-то еще указывает на вашу ошибку, и только оставшиеся 1% обнаружат ошибку, которую вы не сделали сами.

2 голосов
/ 11 ноября 2009

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

В зависимости от ОС вы можете использовать собственный механизм обработки исключенийчтобы достичь большего - например, в Windows вы можете отследить такие вещи, как сбои страниц, используя структурированную обработку исключений.Опять же, не совсем ясно, пойдет ли это на пользу - если необработанное исключение является источником проблемы, это может помочь, но если в коде есть ошибка, где (например) значение X == 10 и значение Y== 20 приводит к бесконечному циклу, или что-то в этом порядке, вам, вероятно, придется придумывать, когда код падает, и уверять, что это никогда не произойдет.

1 голос
/ 11 ноября 2009

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

0 голосов
/ 21 декабря 2009

try / catch для исключений C ++, что вам нужно использовать, это

__try {
} __except(EXCEPTION_EXECUTE_HANDLER) {
}

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

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

long WINAPI filter(EXCEPTION_POINTERS * pex)
{
   EXCEPTION_RECORD * per = pex->ExceptionRecord;
   DWORD dwCode = per->ExceptionCode;

   if (EXCEPTION_DATATYPE_MISALIGNMENT == dwCode)
      return EXCEPTION_CONTINUE_SEARCH; // let a handler above us deal with it.
   else if (EXCEPTION_FLT_DIVIDE_BY_ZERO == dwCode)
      return EXCEPTION_EXECUTE_HANDLER; // Eat this one

   return EXCEPTION_CONTINUE_SEARCH; // let all the rest on through...
}

__try {
 ...
} __except(filter(GetExceptionInformation())) {
}
0 голосов
/ 11 ноября 2009

Вы можете изучить Структурную обработку исключений. Механизмы структурированной обработки исключений и обработки завершений являются неотъемлемой частью операционной системы Windows. MSDN, ссылка

0 голосов
/ 11 ноября 2009

Хотя win32 API является библиотекой C и не использует исключения, MSVC может реализовывать определенные вещи как исключения (например, деление на ноль), которые не должны выполняться таким образом (по стандарту C ++). Итак: это зависит.

Ваш лучший выбор - выяснить причину проблемы и устранить ее.

...