jeudi 21 février 2019

UE4 C++ - Adding an object with a `TArray` member by value to a `TArray` causes a segfault

I have some code that creates a vector of strings in one function, converts that to a TArray<FString>, assigns it to the member variable of an object, and adds that object to a TArray, something like below:

void MyMethod() {
   std::vector<std::string> vec = GetVec();
   TArray<FString> arr = VecStrToTArrFStr(vec);

   MyObject obj;
   obj.value = arr;

   this->Objects.Add(obj);
} 

Where the function VecStrToTArrFStr is as follows:

inline TArray<FString> VecStrToTArrFStr(std::vector<std::string> &vec) {
  TArray<FString> arr;
  arr.SetNumUninitialized(vec.size());

  for (auto &item : vec) {
    arr.Add(FString(UTF8_TO_TCHAR(item.c_str())));
  }

  return arr;
}

This issue occurs on this line:

this->Objects.Add(obj);

For some reason, copying the array throws a segfault. Specifically, it gives this call stack:

  • __memcpy_avx_unaligned (@7fffec5b4ea0..7fffec5b5226:173)
  • FGenericPlatformMemory::Memcpy(void*, void const*, unsigned long) (/UnrealEngine/Engine/Source/Runtime/Core/Public/GenericPlatform/GenericPlatformMemory.h:348)
  • FMemory::Memcpy(void*, void const*, unsigned long) (/UnrealEngine/Engine/Source/Runtime/Core/Public/HAL/UnrealMemory.h:124)
  • TEnableIf<TIsBitwiseConstructible<wchar_t, wchar_t>::Value, void>::Type ConstructItems<wchar_t, wchar_t>(void*, wchar_t const*, int) (/UnrealEngine/Engine/Source/Runtime/Core/Public/Templates/MemoryOps.h:137)
  • void TArray<wchar_t, FDefaultAllocator>::CopyToEmpty<wchar_t>(wchar_t const*, int, int, int) (/UnrealEngine/Engine/Source/Runtime/Core/Public/Containers/Array.h:2508)
  • TArray<wchar_t, FDefaultAllocator>::TArray(TArray<wchar_t, FDefaultAllocator> const&) (/UnrealEngine/Engine/Source/Runtime/Core/Public/Containers/Array.h:338)
  • FString::FString(FString const&) (/UnrealEngine/Engine/Source/Runtime/Core/Public/Containers/UnrealString.h:73)
  • TEnableIf<!(TIsBitwiseConstructible<FString, FString>::Value), void>::Type ConstructItems<FString, FString>(void*, FString const*, int) (/UnrealEngine/Engine/Source/Runtime/Core/Public/Templates/MemoryOps.h:126)
  • void TArray<FString, FDefaultAllocator>::CopyToEmpty<FString>(FString const*, int, int, int) (/UnrealEngine/Engine/Source/Runtime/Core/Public/Containers/Array.h:2508)
  • TArray<FString, FDefaultAllocator>::TArray(TArray<FString, FDefaultAllocator> const&) (/UnrealEngine/Engine/Source/Runtime/Core/Public/Containers/Array.h:338)
  • MyObject::MyObject(MyObject const&) (MyObject.h)
  • int TArray<MyObject, FDefaultAllocator>::Emplace<MyObject const&>(MyObject const&&&) (/UnrealEngine/Engine/Source/Runtime/Core/Public/Containers/Array.h:1843)
  • TArray<MyObject, FDefaultAllocator>::Add(MyObject const&) (/UnrealEngine/Engine/Source/Runtime/Core/Public/Containers/Array.h:1916)

Everything runs perfectly fine if I change MyObject.value to be of type std::vector<std::string> and just assign it the vec, but attempting to assign it a TArray<FString> throws a segfault.

What could be causing this? Does it have something to do with how I'm creating my FString objects, or how I'm creating my TArray? Is UE4 doing some garbage collection on the TArray in VecStrToArrFStr or something?

Aucun commentaire:

Enregistrer un commentaire