Марк Гравелл уже дал отличный ответ; видя, как я частично «вдохновил» этот вопрос, я хотел бы добавить одну вещь:
Одним из основных принципов обработки исключений является никогда не создавать исключение в обработчике исключений. (Примечание. Повторное выбрасывание исключения, относящегося к домену, и / или переноса в порядке; я говорю о том, неожиданное исключение здесь.)
Существует множество причин, по которым вам нужно предотвратить это:
В лучшем случае вы маскируете исходное исключение; становится невозможно точно знать, где изначально произошла ошибка программы.
В некоторых случаях среда выполнения может просто не в состоянии обработать необработанное исключение в обработчике исключений (скажем, в 5 раз быстрее). Например, в ASP.NET установка обработчика исключений на определенных этапах конвейера и сбой в этом обработчике просто уничтожит запрос - или аварийно завершит рабочий процесс, я забыл, какой.
В других случаях вы можете открыть себя до возможности бесконечного цикла в обработчике исключений. Это может показаться глупым поступком, но я видел случаи, когда кто-то пытается обработать исключение, регистрируя его, а когда происходит сбой регистрации ... они пытаются записать ошибку. Большинство из нас, вероятно, не будут сознательно писать код, подобный этому, но в зависимости от того, как вы структурируете обработку исключений вашей программы, вы можете сделать это случайно.
Так какое это имеет отношение к OutOfMemoryException
конкретно?
OutOfMemoryException
ничего не говорит вам о , почему сбой выделения памяти. Вы можете предположить , что это потому, что вы пытались выделить огромный буфер, но, возможно, это не так. Возможно, какой-то другой мошеннический процесс в системе буквально использовал все доступное адресное пространство, и у вас не осталось ни одного байта. Может быть, какой-то другой поток в вашей собственной программе пошел не так, как надо, и пошел в бесконечный цикл, выделяя новую память на каждой итерации, и этот поток уже давно потерпел неудачу, когда OutOfMemoryException
заканчивается в вашем текущем стеке Рамка. Дело в том, что вы на самом деле не знаете, насколько плоха ситуация с памятью, даже если вы думаете, что вы .
Так что начинайте думать об этой ситуации сейчас. Некоторые операции просто не удалось в неуказанной точке глубоко в недрах .NET Framework и распространяются до OutOfMemoryException
. Какую значимую работу вы можете выполнить в вашем обработчике исключений, который не включает выделение дополнительной памяти? Запись в файл журнала? Это требует памяти. Покажите сообщение об ошибке? Это занимает еще больше памяти. Отправить оповещение по электронной почте? Даже не думай об этом.
Если вы попытаетесь сделать это - и потерпите неудачу - тогда у вас будет недетерминированное поведение. Вы, возможно, замаскируете ошибку нехватки памяти и получите таинственные отчеты об ошибках с таинственными сообщениями об ошибках, пузырящимися от всех типов низкоуровневых компонентов, которые вы написали, которые не должны быть в состоянии сбоя. По сути, вы нарушили инварианты вашей собственной программы, и это будет кошмар для отладки, если ваша программа будет работать в условиях нехватки памяти.
Один из аргументов, представленных мне ранее, заключался в том, что вы можете перехватить OutOfMemoryException
и затем переключиться на код с меньшим объемом памяти, например, меньший буфер или потоковую модель. Тем не менее, это Expection Handling"является хорошо известным анти-паттерном. Если вы знаете, что собираетесь сжечь огромный объем памяти и не уверены, может ли система справиться с этим, тогда проверьте доступную память , или еще лучше, просто рефакторинг вашего кода так что ему не нужно так много памяти сразу. Не полагайтесь на OutOfMemoryException
, чтобы сделать это за вас, потому что - кто знает - может быть, выделение едва удастся и вызовет кучу ошибок нехватки памяти сразу после ваш обработчик исключений (возможно, в каком-то совершенно другом компоненте).
Итак, мой простой ответ на этот вопрос: Никогда.
Мой ласковый ответ на этот вопрос: Все нормально в глобальном обработчике исключений, если вы действительно очень осторожны. Не в блоке try-catch.