For some reason, returning a string from a DLL function crashes my program on runtime with the error Unhandled exception at 0x775dfbae in Cranberry Library Tester.exe: Microsoft C++ exception: std::out_of_range at memory location 0x001ef604..
.
I have verified it's not a problem with the function itself by compiling the DLL code as an .exe
and doing a few simple tests in the main
function.
Functions with other return types (int
, double
, etc.) work perfectly.
- Why does this happen?
- Is there a way to work around this behavior?
Source code for DLL:
// Library.h
#include <string>
std::string GetGreeting();
.
// Library.cpp
#include "Library.h"
std::string GetGreeting()
{
return "Hello, world!";
}
Source code for tester:
// Tester.cpp
#include <iostream>
#include <Library.h>
int main()
{
std::cout << GetGreeting()
}
EDIT: I'm using VS2010.
Conclusion
A workaround is to make sure the library and source are compiled using the same compiler with the same options, etc.
Just like user295190 and Adam said that it would work fine if with the exactly same compilation settings.
For example, in Qt QString::toStdString() would return a std::string and you could use it in your EXE from QtCore.dll.
It would crash if DLL and EXE had different compiling settings and linking settings. For example, DLL linked to MD and EXE linked to MT CRT library.
You may return a
std::string
from a class as long as you inline the function that creates the string. This is done, for example, by the Qt toolkit in theirQString::toStdString
method:The inline function is compiled with the program that uses the dll, not when the dll is compiled. This avoids any problems encountered by incompatible runtimes or compiler switches.
So in fact, you should only return standard types from your dll (such as
const char *
andint
above) and add inline functions to convert them tostd::string()
.Passing in a
string &
parameter may also be unsafe because they are often implemented as copy on write.This occurs because you're allocating memory in one DLL (using std::string's constructor), and freeing it in another DLL. You can't do that because each DLL typically sets up it's own heap.
Since your error message indicates you're using Microsoft C++ I'll offer an MS specific answer.
As long as you compile both the EXE and the DLL with the SAME compiler, and both link the the SAME version of the runtime DYNAMICALLY then you'll be just fine. For example, using "Multi-threaded DLL" for both.
If you link against the runtime statically, or link against different versions of the runtime then you're SOL for the reasons @Billy ONeal points out (memory will be allocated in one heap and freed in another).
I had such problem that has been solved by:
using runtime library as DLL for both the application and the DLL (so that allocation is handle in a unique place)
making sure all project settings (compiler, linker) are the same on both project
Just like snmacdonald I was unable to repro your crash, under normal circumstances. Others already mentioned: Configuration Properties -> Code Generation -> Runtime Library must be exactly the same
If I change one of them I get your crash. I have both the DLL and EXE set to Multi-Threaded DLL.