【问题标题】:UE4 C++ - Adding an object with a `TArray` member by value to a `TArray` causes a segfaultUE4 C++ - 将具有“TArray”成员的对象按值添加到“TArray”会导致段错误
【发布时间】:2019-07-15 16:10:15
【问题描述】:

我有一些代码在一个函数中创建字符串向量,将其转换为TArray<FString>,将其分配给对象的成员变量,然后将该对象添加到TArray,如下所示:

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

   MyObject obj;
   obj.value = arr;

   this->Objects.Add(obj);
} 

其中函数VecStrToTArrFStr如下:

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->Objects.Add(obj);

由于某种原因,复制数组会引发段错误。具体来说,它给出了这个调用堆栈:

  • __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&lt;TIsBitwiseConstructible&lt;wchar_t, wchar_t&gt;::Value, void&gt;::Type ConstructItems&lt;wchar_t, wchar_t&gt;(void*, wchar_t const*, int) (/UnrealEngine/Engine/Source/Runtime/Core/Public/Templates/MemoryOps.h:137)
  • void TArray&lt;wchar_t, FDefaultAllocator&gt;::CopyToEmpty&lt;wchar_t&gt;(wchar_t const*, int, int, int) (/UnrealEngine/Engine/Source/Runtime/Core/Public/Containers/Array.h:2508)
  • TArray&lt;wchar_t, FDefaultAllocator&gt;::TArray(TArray&lt;wchar_t, FDefaultAllocator&gt; const&amp;) (/UnrealEngine/Engine/Source/Runtime/Core/Public/Containers/Array.h:338)
  • FString::FString(FString const&amp;) (/UnrealEngine/Engine/Source/Runtime/Core/Public/Containers/UnrealString.h:73)
  • TEnableIf&lt;!(TIsBitwiseConstructible&lt;FString, FString&gt;::Value), void&gt;::Type ConstructItems&lt;FString, FString&gt;(void*, FString const*, int) (/UnrealEngine/Engine/Source/Runtime/Core/Public/Templates/MemoryOps.h:126)
  • void TArray&lt;FString, FDefaultAllocator&gt;::CopyToEmpty&lt;FString&gt;(FString const*, int, int, int) (/UnrealEngine/Engine/Source/Runtime/Core/Public/Containers/Array.h:2508)
  • TArray&lt;FString, FDefaultAllocator&gt;::TArray(TArray&lt;FString, FDefaultAllocator&gt; const&amp;) (/UnrealEngine/Engine/Source/Runtime/Core/Public/Containers/Array.h:338)
  • MyObject::MyObject(MyObject const&amp;) (MyObject.h)
  • int TArray&lt;MyObject, FDefaultAllocator&gt;::Emplace&lt;MyObject const&amp;&gt;(MyObject const&amp;&amp;&amp;) (/UnrealEngine/Engine/Source/Runtime/Core/Public/Containers/Array.h:1843)
  • TArray&lt;MyObject, FDefaultAllocator&gt;::Add(MyObject const&amp;) (/UnrealEngine/Engine/Source/Runtime/Core/Public/Containers/Array.h:1916)

如果我将MyObject.value 更改为std::vector&lt;std::string&gt; 类型并仅将其分配为vec,则一切运行良好,但尝试为其分配TArray&lt;FString&gt; 会引发段错误。

这可能是什么原因造成的?这与我如何创建FString 对象或我如何创建TArray 有关吗? UE4 是在 VecStrToArrFStr 中的 TArray 上做一些垃圾收集吗?

【问题讨论】:

    标签: arrays c++11 unreal-engine4


    【解决方案1】:

    你已经用垃圾 FString 对象填充了数组;当您调用 TArray::Add 时,FString 复制构造函数会尝试对其成员执行按位复制,从而取消引用垃圾指针,从而导致 sigsegv。

    要解决,请移除对SetNumUninitialized的调用;它没有做你认为它做的事情。这个调用不只是保留空间,您实际上是在数组中添加指定数量的垃圾(未初始化)FStrings,然后将“真实”的放在它们的末尾。看看你的数组在调用VecStrToTArrFStr 后最终处于什么状态。

    https://api.unrealengine.com/INT/API/Runtime/Core/Containers/TArray/SetNumUninitialized/index.html

    【讨论】:

    • 啊,就是这样。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多