Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Heap corruption when returning from function inside a dll

I have a function with a prototype like the following:

void function(std::string str);

This function is called in my main function in another program that loads and uses that dll.

function("some string value here");

When returning from this function I get heap corruption error:

Windows has triggered a breakpoint in program.exe.

This may be due to a corruption of the heap, which indicates a bug in program.exe or any of the DLLs it has loaded.

This may also be due to the user pressing F12 while program.exe has focus.

The output window may have more diagnostic information.

Playing around with my code I noticed a few strange observations:
1. When length of the string passed in is less than 11 characters I get no errors, as soon as I add more characters the error appears.
2. When changing the type of parameter from std::string to std::string& the error disappears. The idea of passing reference came from here.
3. I've commented out the body of the function. The operations in there have nothing to do with the exception produced.
4. Changing parameter type from std::string to char* also solves the problem.
What could be causing this error? How do I solve it?

like image 550
atoMerz Avatar asked Dec 03 '12 07:12

atoMerz


1 Answers

Most likely, you're seeing crashes due to the fact that, in Windows, DLLs have their own private heap.

When you compiled your function, the compiler generated some code for std::string's destructor, to clean up its arguments. This code frees the allocated memory on the DLL heap. However, the application EXE also generates its own code for std::string's constructor, which allocates the code on the program heap. When you allocate on one heap and free on the other, undefined behavior occurs, and you crash.

As for why small strings don't trigger the bug - many std::string implementations inline small strings into the struct itself, to avoid heap overhead. When your string is small enough to fit, no memory allocation need take place, and thus it happens to appear to work... as long as you use the same STL version for both EXE and DLL, and the threshold for inlining never changes.

To avoid this issue, don't pass objects by value to DLLs (unless they are POD objects), and don't free an object in a different DLL or EXE than it was created in. Avoid passing STL or C++ library objects around as well, as their implementation may differ between different versions of the C++ compiler. Pass POD objects or C primitive types such as const char * instead.

like image 138
bdonlan Avatar answered Sep 30 '22 20:09

bdonlan