Returning Strings from DLL Functions

2019-02-09 02:25发布

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.

7条回答
看我几分像从前
2楼-- · 2019-02-09 02:48

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.

查看更多
混吃等死
3楼-- · 2019-02-09 02:51

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.

查看更多
劫难
4楼-- · 2019-02-09 02:54

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.

查看更多
兄弟一词,经得起流年.
5楼-- · 2019-02-09 02:59

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).

查看更多
闹够了就滚
6楼-- · 2019-02-09 02:59

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

查看更多
看我几分像从前
7楼-- · 2019-02-09 03:04

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.

查看更多
登录 后发表回答