I am calling into a statically linked .dll, and I see this error:
I wr
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.
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 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.
In this case, the problem is that I was passing a std::string
back across a .dll boundary.
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.
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.
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.
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.