Using std::string in external library

I’m trying to use an external library that heavily uses std::string, and I observe an exception on the very first constructor (in the first string destructor call), when it tries to deallocate the internal memory of a string.

I reproduced the issue with a trivial class that just takes a string in it constructor.

#include <string>

class StringTest
{
public:
	std::string stringField;

	DLL_API StringTest(std::string s)
	: stringField(s)
    {
    }

	DLL_API ~StringTest();
};

I put this class in a dll library built with VS2013 and referenced in my UE4.9 VS Project.

I call this code in an actor c++ class implementation

// Called when the game starts or when spawned
void ATestActor::BeginPlay()
{
	Super::BeginPlay();

	StringTest myStringTest("test"); // crash in this
}

Here is the stack trace I get

 	msvcr120d.dll!00007ff9b79ad1d0()
 	dll_test_string.dll!std::allocator<char>::deallocate(char * _Ptr, unsigned __int64 __formal) Line 574
 	dll_test_string.dll!std::_Wrap_alloc<std::allocator<char> >::deallocate(char * _Ptr, unsigned __int64 _Count) Line 859
 	dll_test_string.dll!std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Tidy(bool _Built, unsigned __int64 _Newsize) Line 2284
 	dll_test_string.dll!std::basic_string<char,std::char_traits<char>,std::allocator<char> >::~basic_string<char,std::char_traits<char>,std::allocator<char> >() Line 992
 	dll_test_string.dll!StringTest::StringTest(std::basic_string<char,std::char_traits<char>,std::allocator<char> > s) Line 7
    UE4Editor-BoidsViewer.dll!ATestActor::BeginPlay() Line 64

Refactoring the libraries that uses std::string would be impractical.

How can I avoid this error?

This does not seems to be UE4 issue, crash happens inside C++ library in it’s allocator which UE4 does not have any control of. Maybe way you initiate that string in constructor causes the exception.

You will need to convert std::string to FString if you wish to use it in UE4 APIs and reflection system, those things gonna be useful as you can bring both types to char*

/reference/string/string/c_str/
FString::operator* | Unreal Engine Documentation note it operator override so you simply add * at the end of varable

Its typically tricky to interface std:: types over dll boundaries. I would advise against it. If you really want to do it, build your interface using char*

See for example: Can std::string be passed across dll boundaries. (i.e) can I export a class with public functions that has std::string params?

Yes I think so, but some clues make me feel this is a runtime problem the constructor and the destructor maybe are not called from the same runtime? (unreal runtime versus mylib runtime)

Okay thanks it works. I have the same issue with the std::map.
How would you do?

My bet is that you construct the std::string using the standard allocator and then its destructed using Unreal’s custom allocator, if that is not supported you are done… About your std::map issue… you could pass plain arrays for both the keys and values and parse that again on both sides… It creates overhead though…

1 Like