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
How to Alpha Blend Rgba Unsigned Byte Color Fast
Linking to Msvc Dll from Mingw
Skipping Incompatible Libraries at Compile
Operator= and Functions That Are Not Inherited in C++
How to Enable C++17 Support in VScode C++ Extension
How to Make a Portable Isnan/Isinf Function
Qt/C++ - Accessing Mainwindow UI from a Different Class
When Will Gnu C++ Support C++11 Without Explicitly Asking for It
Msvc 2015 Universal Crt for App-Local Deployment
How to Update a Printed Message in Terminal Without Reprinting
When Is a Function Try Block Useful
How to Make Elements of Vector Unique? (Remove Non Adjacent Duplicates)
Must the Int Main() Function Return a Value in All Compilers
Creating a Counter That Stays Synchronized Across Mpi Processes