0

I cannot find a solution how to trace a heap corruption error to its root cause in C++.

I have programmed a CPLEX model in C++ and till now everything was fine. I used to test some new instances and now I get all of the sudden heap corruption errors. The application verifier gives me this back:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<avrf:logfile xmlns:avrf="Application Verifier">
    <avrf:logSession TimeStarted="2022-01-27 : 14:40:09" PID="7876" Version="2">
        <avrf:logEntry Time="2022-01-27 : 14:40:27" LayerName="Heaps" StopCode="0xF" Severity="Error">
            <avrf:message>Corrupted suffix pattern for heap block.</avrf:message>
            <avrf:parameter1>1f684551000 - Heap handle used in the call.</avrf:parameter1>
            <avrf:parameter2>1f6871a7fe0 - Heap block involved in the operation.</avrf:parameter2>
            <avrf:parameter3>18 - Size of the heap block.</avrf:parameter3>
            <avrf:parameter4>1f6871a7ff8 - Corruption address.</avrf:parameter4>
            <avrf:stackTrace>
                <avrf:trace>vrfcore!VerifierDisableVerifier+7a7 ( @ 0)</avrf:trace>
                <avrf:trace>verifier!VerifierStopMessage+b9 ( @ 0)</avrf:trace>
                <avrf:trace>verifier!VerifierDisableFaultInjectionExclusionRange+3693 ( @ 0)</avrf:trace>
                <avrf:trace>verifier!VerifierDisableFaultInjectionExclusionRange+39a4 ( @ 0)</avrf:trace>
                <avrf:trace>verifier!VerifierDisableFaultInjectionExclusionRange+b02 ( @ 0)</avrf:trace>
                <avrf:trace>verifier!VerifierDisableFaultInjectionExclusionRange+c3f ( @ 0)</avrf:trace>
                <avrf:trace>verifier!VerifierDisableFaultInjectionExclusionRange+27ad ( @ 0)</avrf:trace>
                <avrf:trace>ntdll!RtlRegisterSecureMemoryCacheCallback+1744 ( @ 0)</avrf:trace>
                <avrf:trace>ntdll!RtlGetCurrentServiceSessionId+1471 ( @ 0)</avrf:trace>
                <avrf:trace>ntdll!RtlGetCurrentServiceSessionId+1324 ( @ 0)</avrf:trace>
                <avrf:trace>ntdll!RtlFreeHeap+51 ( @ 0)</avrf:trace>
                <avrf:trace>vrfcore!VerifierSetAPIClassName+1fc ( @ 0)</avrf:trace>
                <avrf:trace>ucrtbase!free_base+1b ( @ 0)</avrf:trace>
                <avrf:trace>my_exe!std::_Deallocate&lt;16,0&gt;+57 (C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.30.30705\include\xmemory @ 255)</avrf:trace>
                <avrf:trace>my_exe!std::allocator&lt;int&gt;::deallocate+43 (C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.30.30705\include\xmemory @ 823)</avrf:trace>
                <avrf:trace>my_exe!std::vector&lt;int,std::allocator&lt;int&gt; &gt;::_Tidy+b2 (C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.30.30705\include\vector @ 1635)</avrf:trace>
                <avrf:trace>my_exe!std::vector&lt;int,std::allocator&lt;int&gt; &gt;::~vector&lt;int,std::allocator&lt;int&gt; &gt;+2b (C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.30.30705\include\vector @ 588)</avrf:trace>
                <avrf:trace>my_exe!std::vector&lt;int,std::allocator&lt;int&gt; &gt;::`scalar deleting destructor&apos;+23 ( @ 0)</avrf:trace>
                <avrf:trace>my_exe!std::_Default_allocator_traits&lt;std::allocator&lt;std::vector&lt;int,std::allocator&lt;int&gt; &gt; &gt; &gt;::destroy&lt;std::vector&lt;int,std::allocator&lt;int&gt; &gt; &gt;+32 (C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.30.30705\include\xmemory @ 692)</avrf:trace>
                <avrf:trace>my_exe!std::_Destroy_range&lt;std::allocator&lt;std::vector&lt;int,std::allocator&lt;int&gt; &gt; &gt; &gt;+68 (C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.30.30705\include\xmemory @ 937)</avrf:trace>
                <avrf:trace>my_exe!std::vector&lt;std::vector&lt;int,std::allocator&lt;int&gt; &gt;,std::allocator&lt;std::vector&lt;int,std::allocator&lt;int&gt; &gt; &gt; &gt;::_Tidy+87 (C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.30.30705\include\vector @ 1633)</avrf:trace>
                <avrf:trace>my_exe!std::vector&lt;std::vector&lt;int,std::allocator&lt;int&gt; &gt;,std::allocator&lt;std::vector&lt;int,std::allocator&lt;int&gt; &gt; &gt; &gt;::~vector&lt;std::vector&lt;int,std::allocator&lt;int&gt; &gt;,std::allocator&lt;std::vector&lt;int,std::allocator&lt;int&gt; &gt; &gt; &gt;+2b (C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.30.30705\include\vector @ 588)</avrf:trace>
                <avrf:trace>my_exe!Model::~Model+124 ( @ 0)</avrf:trace>
                <avrf:trace>my_exe!Simulation::Simulation+fbd (C:\Users\un_po\source\repos\my_exe\my_exe\Simulation.cpp @ 240)</avrf:trace>
                <avrf:trace>my_exe!main+5c1 (C:\Users\un_po\source\repos\my_exe\my_exe\run.cpp @ 188)</avrf:trace>
                <avrf:trace>my_exe!__scrt_common_main_seh+10c (d:\a01\_work\20\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 288)</avrf:trace>
                <avrf:trace>KERNEL32!BaseThreadInitThunk+14 ( @ 0)</avrf:trace>
                <avrf:trace>ntdll!RtlUserThreadStart+21 ( @ 0)</avrf:trace>
            </avrf:stackTrace>
        </avrf:logEntry>
    </avrf:logSession>
</avrf:logfile>

I read somewhere that I can use the adress to find the error, but unfortunately I am lost. I also enabled page heap in gflag. I tried to run my program in WinDBG, but the code is not executing with command line arguments...

Any advices where to continue from here?

trincot
  • 317,000
  • 35
  • 244
  • 286
PySeeker
  • 818
  • 8
  • 12
  • 1
    Looks like it is hitting the error deleting a vector in your Model class. I suspect that this is nothing to do with CPLEX. – TimChippingtonDerrick Jan 27 '22 at 14:09
  • Thanks a lot @TimChippingtonDerrick. Best way to trace back the specific vector or should I try look at every vector, that is used/initialized in the model class? – PySeeker Jan 27 '22 at 14:15
  • 1
    In general this can be quite difficult, but in practice it is often not too bad. Looks like you are using Visual Studio on Windows, so try using the debugger and put a breakpoint near the start of your Model destructor method. Then run the code, and when it stops at the breakpoint try executing one line of code at a time until you get the error. It's a blunt and lazy way to find it. – TimChippingtonDerrick Jan 28 '22 at 17:07

2 Answers2

0

if you have access to a Linux box, maybe could you try diagnose your problem by using valgrind (https://valgrind.org/)?

0

So I debugged the code for quite some hours and finally found a buffer overflow of a vector, by assign a value outside of the vector length. I don't quite understand why I did not get any error message for that, but I am glad this was over. Some useful post.

Thanks to @TimChippingtonDerrick for giving the right directions.

PySeeker
  • 818
  • 8
  • 12