Why Does This Program Crash: Passing of Std::String Between Dlls

Why does this program crash: passing of std::string between DLLs

This isn't actually being caused by differing heap implementations - the MSVC std::string implementation doesn't use dynamically allocated memory for strings that small (it uses the small string optimization). The CRTs do need to match, but that isn't what bit you this time.

What's happening is that you're invoking undefined behaviour by violating the One Definition Rule.

The release and debug builds will have different preprocessor flags set, and you'll find that std::string has a different definition in each case. Ask your compiler what sizeof(std::string) is - MSVC10 tells me that it's 32 in a debug build and 28 in a release build (this isn't padding - 28 and 32 are both 4 bytes` boundaries).

So what's happening? Variable s is initialized using the debug version of the copy constructor to copy a release version of std::string. The offsets of the member variables are different between the versions, so you copy garbage. The MSVC implementation effectively stores begin and end pointers - you've copied garbage into them; because they're no longer null, the destructor tries to free them and you get an access violation.

Even if the heap implementations were the same it would crash, as you're freeing garbage pointers to memory that was never allocated in the first place.


In summary: the CRT versions need to match but so do the definitions - including the definitions in the standard library.

Unable to pass std::wstring across DLL

You should check that both the EXE and the DLL are dynamically linked with the same debug CRT (/MDd compiler option). Make sure that also other settings like _HAS_ITERATOR_DEBUGGING are the same for both the EXE and the DLL.

(A shortcut could be to just use const wchar_t* instead of std::wstring at the class interface, and just build a std::wstring from the raw pointer inside constructor's body).

EDIT: You confirmed that CRT mismatch (i.e. EXE built with /MD vs. DLL built with /MDd) was the problem. The fact is that the same class name std::wstring means two different classes in debug builds (/MDd) and in release builds (/MD). In fact, in debug builds there can be additional mechanics inside the class implementation to help debugging; this mechanics can introduce inefficiencies, so it's removed in release builds. So, the internal structure of debug build's std::wstring is different from release build's std::wstring (e.g. if you try to print the raw sizeof of std::wstring instances, you can find different numbers in release builds and debug builds). So, the EXE built with /MD was expecting release-build's std::wstring; instead the DLL built with /MDd was expecting debug-build's std::wstring: there is a mismatch between these two expectations (one module is expecting class X but the other module is giving class Y) and so you have a crash.

Crash on returning a System::String that was marshalled from a native C++ call

Hans helped solved this. It was indeed a mismatch between the CRT versions in the native dll and managed dll. I was sure I had already checked this but obviously missed it. The code otherwise works as is. Thanks.

C++ std string different between debug and release dynamic library

Both the caller and the DLL must be built with the same mode type. For example you have function that takes std::string as an argument that is exported from a DLL. If the caller main() is not also compiled in DEBUG it will crash. The compile mode changes the storage definition (secretly) for std:string. So the DEBUG mode definition for std::string in DEBUG mode is different from the definition in release mode. The called function does not agree on the meaning / layout of std::string.
This is likely going to cause a crash.
I suggest passing your string to the dll as a raw pointer. use string.c_str() and consume it as a const char*. This should be fine.

e.g.

QT_API bool STACKMODE bert_Connect(QT_InterfaceManager * inst, const char* IP)

Although since QT_InterfaceManager is opaque it may have similar problems.

VS2013-built C++/CLI DLL crashes using string received from VS2008 C++ app

To use a library built in Visual Studio that has exported C++ functions with standard library parameters or classes that have standard library members, you essentially must use the same version of Visual Studio for the client. This is because each new version of Visual Studio makes changes to the standard library (and thus the client's idea of what a std::string or std::vector is different from what was compiled into the library).

If you need to have the client and library built with different versions of Visual Studio, the only safe way to do this would be to expose the code you need with a strict C interface (const char * instead of std::string, int ar[], int arCount instead of std::vector<int>).



Related Topics



Leave a reply



Submit