Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning Strings from DLL Functions

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.

like image 835
Maxpm Avatar asked Dec 15 '10 04:12

Maxpm


2 Answers

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.

like image 152
Billy ONeal Avatar answered Nov 16 '22 01:11

Billy ONeal


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 their QString::toStdString method:

inline std::string QString::toStdString() const
{ const QByteArray asc = toAscii(); return std::string(asc.constData(), asc.length()); }

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 * and int above) and add inline functions to convert them to std::string().

Passing in a string & parameter may also be unsafe because they are often implemented as copy on write.

like image 37
Mark Beckwith Avatar answered Nov 16 '22 02:11

Mark Beckwith