Question

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?

Was it helpful?

Solution

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.

OTHER TIPS

When exporting DLL functions, it's best if they accept only integral data types, i.e. int or pointers (not sure about float and double).

When you need to pass a string, pass it as a const char *, when you need the DLL function to return a string, pass to the DLL a char * pointer to a pre-allocated buffer, where the DLL would write the string.

Never use memory allocated by the DLL outside of the DLL's own functions, and never pass by value structures that have their own constructor/destructor.

Probably you have linked with static version of C runtime, it is never a good idea to create a DLL that linked with static version of C runtime. This may cause many problems, for example in your program your EXE allocate memory from private heap of static C runtime that it is linked with it, then in your DLL you want to delete that heap and create a new heap(since you want to add some data to the input string and it need to grow its buffer), so it will cause an error. Simplest approach to this is to link all parts of your program(EXE and DLL) with DLL version of C runtime, so they all share same heap from MSVCRTXX.dll

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top