问题
I'm getting a weird access violation at the end of my main whose cause I'm having some difficulties finding.
When shutting down my application I get an access violation in the following:
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**
}
}
Stack trace:
> 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
Anyone got any ideas as to what might cause this?
I read something about facets being cached not sure if thats related?
回答1:
Memory corruption bugs can (obviously) cause this (and many other kinds) of failure.
Have you tried using valgrind (memcheck) or Rational Purify against this? It will probably report the problem (possibly buried in a whole lot of other information if this would be the first time you ran such a check on your code base. You will still want to devise a minimal 'main' implementation that exhibits the behaviour to run under a memory and bounds checker
$0.02
PS. just in case, memory corruption bugs usually arise
- by dereferencing stale pointers (after free/delete)
- by writing beyond the end of an allocated buffer
- by freeing/deleting previously pointers (mostly a symptom of bad ownership tracking)
回答2:
If you override the operator new and use you may meet the same cause as me. the code may be like
#include "yournew" //override new declare ..
#include "fstream"
std::fstream f
f.open(...)
because the iostream is template so the new of _Fac_node use your operator new. but when exit, your memory pool may exit before _Fac_tidy, then when ~_Fac_tidy() run,the program crashed.
回答3:
I believe you're experiencing the same bug I did in the MSVC10 runtime. To my understanding, it is caused by the runtime deleting a global facet when a DLL unloads, and then deleting it again when the process ends. If you link everything statically, it shouldn't happen. It also won't happen in MSVC9, either with static or shared linkage.
回答4:
The first, accepted, response is correct, but it does not show exactly the reason and hence the way of fixing it. According to the listed part of the call stack, I've encountered into the same problem with VC++8 (MS VS 2005) but in the different case: my CLR DLL caused AV at the same point of the code.
From the listed call stack it is seen that the code of <xdebug>
that is normally compiled into msvc*.dll is called but at that moment the _Ptr
already has wrong value. Hence, there is some code that either already freed the object under this pointer or set an exit hook to free the uninitialized object.
If _STATIC_CPPLIB was defined, the <xdebug>
code could be complied into other modules that are loaded into the application process. Then, one exit procedure of those modules could be called prior to another one in msvcp100d.dll and thus could normally free the facet object. In my case, with _STATIC_CPPLIB
defined, both the modules (exe and clr dll) were compiled.
Check the final compiler options in the "Command Line" section for the presence /D "_STATIC_CPPLIB"
. Undefining _STATIC_CPPLIB
and recompiling affected modules fixes the AV at program termination.
_STATIC_CPPLIB
For VC++9 _STATIC_CPPLIB, at MSDN, there is the note that
the combination of the
_STATIC_CPPLIB
preprocessor definition and the/clr
or/clr:pure
compiler option is not supported.
And there are no mentions on _STATIC_CPPLIB
for higher VS versions.
For higher VS versions and VS 10 in particular, I suppose that the code dependent on _STATIC_CPPLIB
still exists. In the TS's case, if _STATIC_CPPLIB
is still used in the compiler options of any TU that includes <string>
or other headers including <locale>
, this improper combination could lead to AV.
来源:https://stackoverflow.com/questions/5559357/debugheapdelete-access-violation-at-termination