Debug Assertion Failed! Expression: _pFirstBlock == pHead

前端 未结 4 1454
陌清茗
陌清茗 2020-12-08 02:14

I am calling into a statically linked .dll, and I see this error:

\"enter

I wr

相关标签:
4条回答
  • 2020-12-08 02:50

    I had the same problem after a Windows reinstallation. My Runtime library build was Multi-threaded Debug DLL (/MDd).

    My solution was to remove *.user file of the visual studio project, remove the debug folder and rebuild the project.

    0 讨论(0)
  • 2020-12-08 02:54

    This is what assert() looks like when its expression argument evaluates to false. This assert exists in the Debug build of the C runtime library, designed to check for allocation problems. The free() function in your case. The Debug build add extra checks to make sure you are writing your code correctly. And tell you when it detects a problem. Like calling free() on an allocation that was already freed, the simple case. Or calling free() passing the wrong pointer value, the trickier case. Or calling free() when the heap was corrupted by earlier code, the much harder case.

    This is only as far as they can take it, they don't actually know why your code got it wrong. There is not any way they can put a Big Red arrow on the code that corrupted the heap for example. The easy case is covered by the Debug + Windows + Call Stack debugger window, it takes you to the code in your program that called free(). Or std::operator delete for a C++ program. The harder case is very, very hard indeed, heap corruption is often a Heisenbug. Getting the assert to be repeatable so you can set a data breakpoint on the reported address is the core strategy. Crossing fingers for the easy case, good luck with it!


    After edit: yes, having cross-module problems with a C++ class like std::string is certainly one of the problems it can catch. Not a Heisenbug, good kind of problem to have. Two basic issues with that:

    • The modules might each have their own copy of the CRT, objects allocated by one copy of the CRT cannot be released by another copy of the CRT. They each have their own heap they allocate from. A problem that got addressed in VS2012, the CRT now allocates from a process-global heap.
    • The modules might not use the same implementation of std::string. With an object layout that does not match. Easily induced by having the modules compiled with different C++ library versions, particularly an issue with C++11 changes. Or different build settings, the _HAS_ITERATOR_DEBUGGING macro is quite notorious.

    The only cure for that problem is to make sure that you build all of the modules in your program with the exact same compiler version using the exact same build settings. Using /MD is mandatory, it ensures that the CRT is shared so there's only one in the program.

    0 讨论(0)
  • 2020-12-08 03:09

    In this case, the problem is that I was passing a std::string back across a .dll boundary.

    Runtime Library config

    • If the MSVC Runtime library is set to Multi-threaded Debug DLL (/MDd), then this is no problem (it works fine).

    • If the MSVC Runtime library is set to Multi-threaded Debug (/MTd), then it will throw this error, which can be fixed with the following instructions.

    Memory allocated in Memory Manager A and freed in Memory Manager B ...

    The problem is that memory is allocated on the .dll side, then that same memory is freed on the application side. This means that memory manager A is allocating memory, and memory manager B is releasing that same memory, which generates errors.

    The solution is to make sure that all memory passed back is not allocated in the DLL. In other words, the memory is always allocated on the application side, and freed on the application side.

    Of course, the DLL can allocate/free memory internally - but it can't allocate memory that is later freed by the application.

    Examples

    This will not work:

    // Memory is allocated on the .dll side, and freed on the app side, which throws error.
    DLL std::string GetString(); 
    

    This will work:

    // Memory is allocated/freed on the application side, and never allocated in the .dll.
    DLL int GetString(std::string& text); 
    

    However, this is not quite enough.

    On the application side, the string has to be pre-allocated:

    std::string text("");
    text.reserve(1024);     // Reserves 1024 bytes in the string "text".
    

    On the .dll side, the text must be copied into the original buffer (rather than overwritten with memory that is allocated on the .dll side):

    text.assign("hello");
    

    Sometimes, C++ will insist on allocating memory anyway. Double check that the pre-allocation is still the same as it was:

    if (text.capacity < 1024)
    {
       cout << "Memory was allocated on the .dll side. This will eventually throw an error.";
    }
    

    Another way that works is to use std::shared_ptr<std::string>, so even though memory is allocated in the .dll, it is released by the .dll (rather than the application side).

    Yet another way is to accept a char * and a length which indicates the amount of pre-allocated memory. If the text that we want to pass back is longer than the length of pre-allocated memory, return an error.

    0 讨论(0)
  • 2020-12-08 03:11

    The likely cause: binding to wrong version of the Qt DLLs, especially when moving a project from VS2010 to VS2012.

    This is due to different versions of the standard library and associated dynamic allocation issues.

    0 讨论(0)
提交回复
热议问题