_DebugHeapDelete Нарушение прав доступа при прекращении - PullRequest
2 голосов
/ 06 апреля 2011

Я получаю странное нарушение прав доступа в конце своей основной программы, причину которой мне трудно найти.

При закрытии моего приложения я получаю нарушение прав доступа в следующих случаях:

Xdebug

        // TEMPLATE FUNCTION _DebugHeapDelete
template<class _Ty>
    void __CLRCALL_OR_CDECL _DebugHeapDelete(_Ty *_Ptr)
    {   // delete from the debug CRT heap even if operator delete exists
    if (_Ptr != 0)
        {   // worth deleting
        _Ptr->~_Ty();
        // delete as _NORMAL_BLOCK, not _CRT_BLOCK, since we might have
        // facets allocated by normal new.
        free(_Ptr); // **ACCESS VIOLATION**
        }
    }

Трассировка стека:

>   msvcp100d.dll!std::_DebugHeapDelete<void>(void * _Ptr)  Line 62 + 0xa bytes C++
    msvcp100d.dll!std::numpunct<char>::_Tidy()  Line 190 + 0xc bytes    C++
    msvcp100d.dll!std::numpunct<char>::~numpunct<char>()  Line 122  C++
    msvcp100d.dll!std::numpunct<char>::`scalar deleting destructor'()  + 0x11 bytes C++
    msvcp100d.dll!std::_DebugHeapDelete<std::locale::facet>(std::locale::facet * _Ptr)  Line 62 C++
    msvcp100d.dll!std::_Fac_node::~_Fac_node()  Line 23 + 0x11 bytes    C++
    msvcp100d.dll!std::_Fac_node::`scalar deleting destructor'()  + 0x11 bytes  C++
    msvcp100d.dll!std::_DebugHeapDelete<std::_Fac_node>(std::_Fac_node * _Ptr)  Line 62 C++
    msvcp100d.dll!_Fac_tidy()  Line 41 + 0x9 bytes  C++
    msvcp100d.dll!std::_Fac_tidy_reg_t::~_Fac_tidy_reg_t()  Line 48 + 0xe bytes C++
    msvcp100d.dll!std::`dynamic atexit destructor for '_Fac_tidy_reg''()  + 0xf bytes   C++
    msvcp100d.dll!_CRT_INIT(void * hDllHandle, unsigned long dwReason, void * lpreserved)  Line 415 C
    msvcp100d.dll!__DllMainCRTStartup(void * hDllHandle, unsigned long dwReason, void * lpreserved)  Line 526 + 0x11 bytes  C
    msvcp100d.dll!_DllMainCRTStartup(void * hDllHandle, unsigned long dwReason, void * lpreserved)  Line 476 + 0x11 bytes   C

Кто-нибудь получил какие-либо идеи относительно того, что может вызвать это?

Я читал что-то о кешируемых гранях, не уверен, что это связано?

Ответы [ 4 ]

4 голосов
/ 13 июля 2011

Если вы переопределите оператор new и use, вы можете столкнуться с той же причиной, что и я.код может быть как

#include "yournew" //override new declare .. 
#include "fstream" 
std::fstream f
f.open(...)

, потому что iostream является шаблоном, поэтому новый из _Fac_node использует ваш оператор new.но при выходе ваш пул памяти может завершиться до _Fac_tidy, затем при запуске ~ _Fac_tidy () программа вылетела.

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

Ошибки повреждения памяти могут (очевидно) вызвать этот (и многие другие виды) сбой.

Вы пытались использовать против этого valgrind (memcheck) или Rational Purify? Вероятно, он сообщит о проблеме (возможно, будет скрыт в большом количестве другой информации, если это будет первый раз, когда вы выполняете такую ​​проверку в своей кодовой базе. реализация, которая демонстрирует поведение, выполняемое при проверке памяти и границ

$ 0,02

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

  • путем разыменования устаревших указателей (после освобождения / удаления)
  • путем записи за пределы выделенного буфера
  • путем удаления / удаления ранее указанных указателей (в основном это признак плохого отслеживания владения)
1 голос
/ 13 декабря 2015

Первый, принятый, ответ правильный, но он не показывает точно причину и, следовательно, способ ее устранения. Согласно перечисленной части стека вызовов, я столкнулся с той же проблемой с VC ++ 8 (MS VS 2005), но в другом случае: моя CLR DLL вызвала AV в той же точке кода.

Из перечисленного стека вызовов видно, что вызывается код <xdebug>, который обычно компилируется в msvc * .dll, но в этот момент _Ptr уже имеет неправильное значение. Следовательно, есть некоторый код, который либо уже освободил объект под этим указателем, либо установил выходной хук для освобождения неинициализированного объекта.

Если определено _STATIC_CPPLIB, код <xdebug> может быть применен к другим модулям, которые загружаются в процесс приложения. Затем одна процедура выхода из этих модулей может быть вызвана до другой в msvcp100d.dll и, таким образом, обычно может освободить объект фасета. В моем случае, с определением _STATIC_CPPLIB, оба модуля (exe и clr dll) были скомпилированы.

Решение для VC ++ 8,9

Проверьте окончательные параметры компилятора в разделе «Командная строка» на наличие /D "_STATIC_CPPLIB". Отмена определения _STATIC_CPPLIB и перекомпиляция затронутых модулей исправляет AV при завершении программы.

Примечание на _STATIC_CPPLIB

Для VC ++ 9 _STATIC_CPPLIB, на MSDN есть примечание, что

комбинация определения препроцессора _STATIC_CPPLIB и /clr или /clr:pure опция компилятора не поддерживается.

И на _STATIC_CPPLIB нет упоминаний для более высоких версий VS. Для более высоких версий VS и VS 10, в частности, я предполагаю, что код, зависящий от _STATIC_CPPLIB, все еще существует. В случае TS, если _STATIC_CPPLIB все еще используется в опциях компилятора любого TU, который включает <string> или другие заголовки, включая <locale>, эта неправильная комбинация может привести к AV.

1 голос
/ 06 октября 2011

Я полагаю, что вы испытываете ту же ошибку , что и я во время выполнения MSVC10. Насколько я понимаю, это вызвано тем, что среда выполнения удаляет глобальный аспект при выгрузке DLL, а затем снова удаляет его, когда завершается процесс. Если вы связываете все статически, этого не должно произойти. Это также не произойдет в MSVC9 со статической или общей связью.

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