在 C++ 中调用 free() 在调试中触发 ntdll!DbgBreakPoint() 但在发布中崩溃

Kem*_*mal 5 c++ windows debugging memory-management

我有一个单线程程序,在非调试模式下运行时,在调用后的某些点上会持续崩溃。free()

\n\n

然而,在调试模式下,free() 即使没有设置断点,调试器也会在调用的行上中断。当我尝试再次进入下一行时,调试器在同一行再次中断。再次单步恢复正常执行。没有崩溃,没有段错误,什么都没有。

\n\n
\n

EDIT-1:与我上面写的相反,非调试模式下的崩溃结果是一致的,这让我觉得我在某种程度上写了一些我不应该写的地方。(不过,调试模式下的中断仍然是一致的。)

\n
\n\n

中断处的调用堆栈显示了在调用语句的函数之后调用的一些 Windows 库函数(我认为)free()。我不知道如何解释它们。因此,我不知道在这种情况下如何进行调试。

\n\n

我在下面的断点处提供了调用堆栈。有人可以指出我可以解决问题的方向吗?什么可能导致调试器模式中断?

\n\n

程序在Windows Vista上运行,使用gcc 4.9.2编译,使用的调试器是gdb。假设双重释放不是这种情况。(我使用::operator new::operator delete重载来捕获这一点。描述的情况在没有这些重载的情况下也是相同的。)

\n\n

请注意,崩溃(或调试器中的非自愿中断)是一致的。每次都会在同一个执行点发生。

\n\n

这是初始中断时的调用堆栈:

\n\n

(请注意,free_wrapper()该函数包含free()导致崩溃/中断的语句。)

\n\n
#0 0x770186ff   ntdll!DbgBreakPoint() (C:\\Windows\\system32\\ntdll.dll:??)\n#1 0x77082edb   ntdll!RtlpNtMakeTemporaryKey() (C:\\Windows\\system32\\ntdll.dll:??)\n#2 0x7706b953   ntdll!RtlImageRvaToVa() (C:\\Windows\\system32\\ntdll.dll:??)\n#3 0x77052c4f   ntdll!RtlQueryRegistryValues() (C:\\Windows\\system32\\ntdll.dll:??)\n#4 0x77083f3b   ntdll!RtlpNtMakeTemporaryKey() (C:\\Windows\\system32\\ntdll.dll:??)\n#5 0x7704bcfd   ntdll!EtwSendNotification() (C:\\Windows\\system32\\ntdll.dll:??)\n#6 0x770374d5   ntdll!RtlEnumerateGenericTableWithoutSplaying() (C:\\Windows\\system32\\ntdll.dll:??)\n#7 0x75829dc6   KERNEL32!HeapFree() (C:\\Windows\\system32\\kernel32.dll:??)\n#8 0x75a99c03   msvcrt!free() (C:\\Windows\\system32\\msvcrt.dll:??)\n#9 0x350000 ?? () (??:??)\n--> #10 0x534020    free_wrapper(pv=0x352af0) (C:\\dm\\bin\\codes\\CodeBlocks\\ProjTemp\\src\\Unrelated\\MemMgmt.cpp:282)\n#11 0x407f74    operator delete(pv=0x352af0) (C:\\dm\\bin\\codes\\CodeBlocks\\ProjTemp\\main.cpp:1002)\n#12 0x629a74    __gnu_cxx::new_allocator<char>::deallocate(this=0x22f718, __p=0x352af0 "\\n\xc3\xbf\xc3\xbf\xc3\xbf\xc3\xbf\xc3\xbf\xc3\xbf\xc2\xba\\r%") (C:/Program Files/CodeBlocks/MinGW/lib/gcc/mingw32/4.9.2/include/c++/ext/new_allocator.h:110)\n#13 0x6c2257    std::allocator_traits<std::allocator<char> >::deallocate(__a=..., __p=0x352af0 "\\n\xc3\xbf\xc3\xbf\xc3\xbf\xc3\xbf\xc3\xbf\xc3\xbf\xc2\xba\\r%", __n=50) (C:/Program Files/CodeBlocks/MinGW/lib/gcc/mingw32/4.9.2/include/c++/bits/alloc_traits.h:383)\n#14 0x611940    basic_CDataUnit<std::allocator<char> >::~basic_CDataUnit(this=0x22f714, __vtt_parm=0x781df4 <VTT for basic_CDataUnit_TDB<std::allocator<char> >+4>, __in_chrg=<optimized out>) (include/DataUnit/CDataUnit.h:112)\n#15 0x61dfa1    basic_CDataUnit_TDB<std::allocator<char> >::~basic_CDataUnit_TDB(this=0x22f714, __in_chrg=<optimized out>, __vtt_parm=<optimized out>) (include/DataUnit/CDataUnit_TDB.h:125)\n#16 0x503898    CTblSegHandle::UpdateChainedRowData(this=0x353cf8, new_row_data=..., old_row_fetch_res=..., vColTypes=..., block_hnd=...) (C:\\dm\\bin\\codes\\CodeBlocks\\ProjTemp\\src\\SegHandles\\CTblSegHandle.cpp:912)\n#17 0x502fcc    CTblSegHandle::UpdateRowData(this=0x353cf8, new_row_data=..., old_row_fetch_res=..., vColTypes=..., block_hnd=...) (C:\\dm\\bin\\codes\\CodeBlocks\\ProjTemp\\src\\SegHandles\\CTblSegHandle.cpp:764)\n#18 0x443272    UpdateRow(row_addr=..., new_data_unit=..., vColTypes=..., block_hnd=..., seg_hnd=...) (C:\\dm\\bin\\codes\\CodeBlocks\\ProjTemp\\src\\DbUtilities.cpp:910)\n#19 0x443470    UpdateRow(row_addr=..., vColValues=..., vColTypes=...) (C:\\dm\\bin\\codes\\CodeBlocks\\ProjTemp\\src\\DbUtilities.cpp:935)\n#20 0x4023e3    test_RowChaining() (C:\\dm\\bin\\codes\\CodeBlocks\\ProjTemp\\main.cpp:234)\n#21 0x4081c6    main() (C:\\dm\\bin\\codes\\CodeBlocks\\ProjTemp\\main.cpp:1034)\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是当我进入下一行并且调试器在恢复正常执行之前最后一次中断时的调用堆栈:

\n\n
#0 0x770186ff   ntdll!DbgBreakPoint() (C:\\Windows\\system32\\ntdll.dll:??)\n#1 0x77082edb   ntdll!RtlpNtMakeTemporaryKey() (C:\\Windows\\system32\\ntdll.dll:??)\n#2 0x77052c7f   ntdll!RtlQueryRegistryValues() (C:\\Windows\\system32\\ntdll.dll:??)\n#3 0x77083f3b   ntdll!RtlpNtMakeTemporaryKey() (C:\\Windows\\system32\\ntdll.dll:??)\n#4 0x7704bcfd   ntdll!EtwSendNotification() (C:\\Windows\\system32\\ntdll.dll:??)\n#5 0x770374d5   ntdll!RtlEnumerateGenericTableWithoutSplaying() (C:\\Windows\\system32\\ntdll.dll:??)\n#6 0x75829dc6   KERNEL32!HeapFree() (C:\\Windows\\system32\\kernel32.dll:??)\n#7 0x75a99c03   msvcrt!free() (C:\\Windows\\system32\\msvcrt.dll:??)\n#8 0x350000 ?? () (??:??)\n--> #9 0x534020 free_wrapper(pv=0x352af0) (C:\\dm\\bin\\codes\\CodeBlocks\\ProjTemp\\src\\Unrelated\\MemMgmt.cpp:282)\n#10 0x407f74    operator delete(pv=0x352af0) (C:\\dm\\bin\\codes\\CodeBlocks\\ProjTemp\\main.cpp:1002)\n#11 0x629a74    __gnu_cxx::new_allocator<char>::deallocate(this=0x22f718, __p=0x352af0 "\\n\xc3\xbf\xc3\xbf\xc3\xbf\xc3\xbf\xc3\xbf\xc3\xbf\xc2\xba\\r%") (C:/Program Files/CodeBlocks/MinGW/lib/gcc/mingw32/4.9.2/include/c++/ext/new_allocator.h:110)\n#12 0x6c2257    std::allocator_traits<std::allocator<char> >::deallocate(__a=..., __p=0x352af0 "\\n\xc3\xbf\xc3\xbf\xc3\xbf\xc3\xbf\xc3\xbf\xc3\xbf\xc2\xba\\r%", __n=50) (C:/Program Files/CodeBlocks/MinGW/lib/gcc/mingw32/4.9.2/include/c++/bits/alloc_traits.h:383)\n#13 0x611940    basic_CDataUnit<std::allocator<char> >::~basic_CDataUnit(this=0x22f714, __vtt_parm=0x781df4 <VTT for basic_CDataUnit_TDB<std::allocator<char> >+4>, __in_chrg=<optimized out>) (include/DataUnit/CDataUnit.h:112)\n#14 0x61dfa1    basic_CDataUnit_TDB<std::allocator<char> >::~basic_CDataUnit_TDB(this=0x22f714, __in_chrg=<optimized out>, __vtt_parm=<optimized out>) (include/DataUnit/CDataUnit_TDB.h:125)\n#15 0x503898    CTblSegHandle::UpdateChainedRowData(this=0x353cf8, new_row_data=..., old_row_fetch_res=..., vColTypes=..., block_hnd=...) (C:\\dm\\bin\\codes\\CodeBlocks\\ProjTemp\\src\\SegHandles\\CTblSegHandle.cpp:912)\n#16 0x502fcc    CTblSegHandle::UpdateRowData(this=0x353cf8, new_row_data=..., old_row_fetch_res=..., vColTypes=..., block_hnd=...) (C:\\dm\\bin\\codes\\CodeBlocks\\ProjTemp\\src\\SegHandles\\CTblSegHandle.cpp:764)\n#17 0x443272    UpdateRow(row_addr=..., new_data_unit=..., vColTypes=..., block_hnd=..., seg_hnd=...) (C:\\dm\\bin\\codes\\CodeBlocks\\ProjTemp\\src\\DbUtilities.cpp:910)\n#18 0x443470    UpdateRow(row_addr=..., vColValues=..., vColTypes=...) (C:\\dm\\bin\\codes\\CodeBlocks\\ProjTemp\\src\\DbUtilities.cpp:935)\n#19 0x4023e3    test_RowChaining() (C:\\dm\\bin\\codes\\CodeBlocks\\ProjTemp\\main.cpp:234)\n#20 0x4081c6    main() (C:\\dm\\bin\\codes\\CodeBlocks\\ProjTemp\\main.cpp:1034)\n
Run Code Online (Sandbox Code Playgroud)\n

小智 -1

您可以使用 valgrind 检查您的代码中是否存在任何无效的读/写或任何无效的空闲。valgrind -v --leak-check=full --show-reachable=yes --log-file=log_valgrind ./Process

log_valgrind 将包含无效的读/写。