2009-07-02 3 views
2

Я получаю следующее исключение, когда запускаю свое приложение в режиме Release из Visual C++.AccessViolationException в режиме выпуска (C++)

Необработанное исключение: System.AccessViolationException: Попытка чтения или записи в защищенную память . Это часто указывает , что другая память повреждена. в _cexit() в .LanguageSupport._UninitializeDefaultDomain (Пустота * печенье) в .LanguageSupport.UninitializeDefaultDomain() в .LanguageSupport.DomainUnload (Object источника, Ева ntArgs аргументы) в .ModuleUninitializer.SingletonDomainUnload (объективистский источнике т , Аргументы EventArgs)

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

Кроме того, я обнаружил, что при добавлении трех константных std :: string переменных исключение было выбрано. Если я удалю, тогда все пойдет хорошо.

Другая часть информации: Я обнаружил, что отключив все оптимизации компилятора в режиме выпуска делает исключение уходит

Что-то подозрительное происходит. Любые идеи о том, как отслеживать это?

Спасибо за помощь, Джо

+0

Выглядит как переполнение буфера или указатель испортился. В этих случаях ошибка * может * быть где-то непосредственно перед точкой, в которой возникает исключение ... если вам повезет. Счастливая отладка. –

ответ

3

Joe, у вас есть memory leak.

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

См. this article Общие причины утечек памяти и их идентификация, в противном случае поиск «Профилировщик памяти C++» + ваш компилятор/платформа, он предоставит ссылки на профилировщики памяти, подходящие для вашего компилятора и платформы, эти поможет отслеживать утечку памяти, наблюдая, как ваша программа использует память при ее запуске.

Надеюсь, это поможет.

EDIT

Как отслеживать его вниз? Это не в моей голове, может быть лучше советовать где-нибудь еще. , ,

Найти, где произошел сбой кода, при доступе к содержимому некоторого указателя (или удалению указателя). Проблема в том, что этот указатель имеет либо: a) никогда не назначаемый b) уже удален. Пройти все ссылки на указатели этого типа, используются ли они в операциях copy ctors/assign?

Если да, то это содержимое копируется или просто указатель? Если только указатель тогда является классом, который пытается удалить указатель? Если так, то первый класс, который умрет, будет успешным, второй будет нарушать доступ.

Если вы явно не кодируете копии ctors и operator =, то вам следует скрыть их (объявить частные прототипы, но не выполнять их), это прекратит компилятор от генерации реализаций по умолчанию для вас.

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

Я в отпуске с завтрашнего дня или двух недель, напишите мне прямо сегодня (перейдите по ссылке на моей странице пользователя SO), если у вас есть какие-либо вопросы по этому вопросу.

+0

Спасибо. Я думаю ты прав. У нас было много проблем с утечками (я предполагаю, что это подходит для курса). Мы используем средства утечки памяти MS: _CrtSetReportMode (_CRT_WARN, _CRTDBG_MODE_FILE); _CrtSetReportFile (_CRT_WARN, _CRTDBG_FILE_STDERR); _CrtSetBreakAlloc (665); Состояние _CrtMemState; _CrtMemCheckpoint (& state); Любые мысли о том, как отслеживать это? – Joe

2

У вас есть код, который с помощью #define за отладки в вашем коде?

т.е.

#ifndef _DEBUG 
    //release only code such as liscensing code 
#endif 

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

Другая возможность - проблема VS (или любая другая IDE, которую вы используете). Попробуйте запустить release .exe напрямую, а не через среду разработки и посмотрите, есть ли у вас такая же проблема.

+0

Я рассмотрю это. Благодарю. – Joe

+0

ничего не нашел. – Joe

+0

Неужели это все еще сбой при запуске .exe напрямую? – CodeFusionMobile

1

Прошло некоторое время, так как я сделал C++ «в гневе», так сказать, некоторые (или даже все) того, что я говорю ниже, могут быть устаревшими.

Вы используете управляемый C++? Если нет, то это звучит как неинициализированный указатель. Раньше было, что все указатели были отброшены в отладочном состоянии & Я помню что-то об отключении этого поведения, но я не могу вспомнить подробные сведения прямо сейчас.

Являются ли строки обгонами их переменных? Вряд ли с std :: string, но стоит устранить.

+0

Я не использую CLR, поэтому я думаю, что код не управляется, не так ли? Интересно, что я уменьшил размер строки, используемой для инициализации переменной const std :: string, и увидел, что исключение исчезло. Означает ли это, что строка обгоняет переменную? Спасибо. – Joe

+0

Как я уже сказал, прошло некоторое время с тех пор, как я сделал C++ и никогда не управлял кодом, но если вы не используете CLR, я бы предположил, что ваш код не управляется. Если изменение строки изменит поведение, то это будет указывать на то, что в этом проблема лежит, но на самом деле сидеть и отлаживать код всегда будет трудно быть уверенным. – ChrisF

+0

Будут ли управляемые переполнения буфера кода? Я думал, что основным преимуществом было сбор мусора, но я не эксперт. –

1

Пара возможностей:

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

Другая возможность заключается в том, что у вас есть неинициализированный указатель где-то. VC default инициализирует локальные переменные в режиме отладки, но не в режиме деблокирования. Таким образом, код типа:

int* p; 
if (p != NULL) { /* do something */ } 

Обычно не работает в режиме деблокирования.

+0

Большое спасибо. Первая возможность кажется более вероятной, чем вторая для меня. Я говорю это, потому что я могу избавиться от исключения, изменив размер некоторых строк. Если это была проблема инициализации указателя, я должен все еще видеть исключение, правильно? – Joe

+0

@Joe - если бы это был указатель инициализации, вы не увидите его в отладке, поскольку оба @eidolon и я указываем по умолчанию. VC инициализирует локальные переменные в режиме отладки. – ChrisF

+0

Справа. Я могу сделать исключение, изменив размеры строк в режиме * Release *. – Joe

0

Сообщение об ошибке настоятельно предлагает вам проблему с памятью, возможно, переписывая память. Их сложно найти, но вы можете найти некоторые возможные решения для поиска вирусов с помощью средства визуализации C++ memory.

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

Скручивание с отладкой по сравнению с выпуском, добавление или удаление частей кода, изменение параметров оптимизации и т.п. вряд ли разрешит проблему. Даже если это произойдет, это может произойти, если будут сделаны какие-либо изменения.

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

Вы также можете ознакомиться с практикой своего магазина. Используете ли вы менее безопасные конструкции (new, а не vector<>, скажем)? У вас есть стандарты кодирования, чтобы попытаться снизить риск? У вас есть обзоры кода? Повреждение памяти может быть коварным и повреждающим, и вы хотите избежать его как можно больше.

0

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

Здесь есть замечательная статья http://www.thunderguy.com/semicolon/2002/08/15/visual-c-exception-handling/ (страница 3), которая показывает, как создать класс исключения Windows, который поймает исключение с помощью метода _set_se_translator и выбросит исключение C++. Самое замечательное в том, что вы можете получить стек из структуры EXCEPTION_RECORD, хотя вам придется добавить эту функциональность для обработки структуры, но это поможет сузить поиск этого нарушения доступа.

0

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

Попробуйте искать неинициализированную переменную, доступ которой может вызвать исключение.

Предположим, что у вас есть логическая переменная типа boolean.

bool bRet; 

В сборке отладки bRet получит инициализацию до 0, и ваш код просто отлично работает.

Но в выпуске не будет 0, это будет некоторая случайная величина, и ваш код может делать что-то на основе bRet. Это может привести к исключению, потому что значение bRet неверно.

+0

Спасибо. Я займусь этим. – Joe

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