2009-10-28 4 views
3

Я пытаюсь отслеживать сбой, который случается, когда я подчеркиваю свой код C# и работаю в условиях низкой памяти. Однако в некоторых случаях вместо получения OutOfMemoryException моя программа просто сбой и выход. Обычно это происходит из-за повреждения памяти из-за превышения буфера или из-за переполнения стека (или повреждения).Проверка целостности кучи и размера стека в C#

Итак, есть способ запустить проверку целостности кучи, или есть способ проверить, сколько стека осталось в потоке?

Я использую много небезопасного кода по соображениям скорости, поэтому вполне вероятно, что у меня есть код, искажающий память где-то. К сожалению, авария происходит случайно, после того, как происходит коррупция. Я понимаю, что C# закрывает приложение, когда обнаруживает переполнение буфера, но есть ли способ заставить его сделать чек?

Спасибо.

+0

Выходит ли он без каких-либо исключений? Пробовали ли вы компиляцию и тестирование как в режиме выпуска, так и в режиме отладки? То, что вы хотите, - это диалоговое окно, сообщающее вам, например. «необработанное исключение» или «ошибка сегментации» или что-то подобное, чтобы дать вам ключ. – csl

+0

Да, он просто выходит без каких-либо исключений. Я тестировал как в режимах выпуска, так и в режиме отладки. Нет разницы. Вы можете получить аналогичный сбой, используя stackalloc, чтобы запросить гораздо больше памяти из стека, а затем фактически доступен. То есть вы не получаете исключение переполнения стека, программа просто выходит. Обратите внимание, что этот сбой ТОЛЬКО происходит в условиях низкой памяти. Так что, возможно, это не коррупция. Возможно, что-то вроде JIT исчерпывает память и вызывает этот выход. – AZDean

+0

Также обратите внимание, что мне пришлось отключить автоматическую настройку виртуальной памяти, чтобы принудительно установить условие низкой памяти. Другими словами, я действительно заставляю его исчерпывать память. Я читаю о «ограниченной области выполнения», но я не вижу, как это мне поможет. Эта проблема приводит к сбою моей программы в непредсказуемых точках кода повсюду. Я не могу сделать всю свою программу CER. – AZDean

ответ

3

Вы можете обрабатывать эти ситуации с помощью Constrained Execution Regions:

ограничена область выполнения (CER) является частью механизма авторинга надежного управляемого кода. CER определяет область, в которой общая среда исполнения CLR ограничена из-за исключения исключений вне зоны, которые препятствовали бы выполнению кода в этой области целиком. Внутри этого региона код пользователя ограничен от выполнения кода, который приведет к выбросу внеполосных исключений. Метод PrepareConstrainedRegions должен немедленно предшествовать блоку try и отметки catch, finally и fault блокируются как области с ограниченным исполнением. После того, как он помечен как ограниченный регион, код должен вызывать только другой код с сильными контрактами надежности, а код не должен выделять или делать виртуальные вызовы неподготовленными или ненадежными методами, если только код не готов обрабатывать сбои. CLR задерживает поток прерываний для кода, который выполняется в CER.

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

1

Существуют определенные условия, когда ОС не имеет иного выбора, кроме как уничтожить процесс. Чтобы повысить исключение, например переполнение стека или отказ сегмента в процессе, ядро ​​должно написать EXCEPTION_RECORD в стеке ошибок, прежде чем он вернет управление процессу. Если нет места для записи этой записи, процесс просто исчезает, и вы ничего не можете сделать, чтобы остановить его. Две ситуации, которые я знаю об этом, могут произойти, если вы продолжаете наращивать стек после EXCEPTION_STACK_OVERFLOW или если зарезервированная страница стека не может быть зафиксирована, то они являются довольно редкими ситуациями.

Лучше всего исправить повреждение. Попробуйте запустить под защитой gflags PageHeap. Если вы знаете место возникновения исключения, попробуйте установить точку прерывания перерыва в буфере в отладчике. Или попробуйте идентифицировать посмертный шрифт от шаблона записи (может быть, например, строка) или от поиска в памяти для ссылок обратно в буфер.

2

При попытке разыскать мою проблему, я нашел эти статьи были очень полезны:

Investigating Memory Issues

When memory is running low…

IGCHost Interface

Getting the most out of .NET by taking control

В последней статье говорится следующее :

Если память не может быть выделена для объектов исключения, среда выполнение будет прекратиться без предоставления за исключением обработчиков шанса выполнить, который редко будет желаемое поведение. [Так], а не просто отказываются выделить любую дополнительную память, более мягкий и более эффективный метод заключается в позволяет небольшое увеличение памяти так объекты исключения могут быть успешно создан, и OutOfMemory исключение может корректно брошено и обрабатывается управляемый код.

Я считаю, что это то, что мне нужно сделать, чтобы избежать моей проблемы. Поскольку мое приложение очень интенсивно работает с памятью, я не могу позволить ему перегрузить память в файл подкачки, так как это ОЧЕНЬ, ОЧЕНЬ медленно. Мне нужно мое приложение, чтобы ограничить себя физической памятью, чтобы поддерживать работоспособность. Но когда у него заканчивается память, мне нужно исключение из памяти. Я НЕ МОГУ ЗАПРЕЩАЕТСЯ, чтобы приложение просто разбилось!

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

Смежные вопросы