You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unreal项目中AWS C++ SDK GetObject析构触发段错误求助

AWS C++ SDK在Unreal中S3 GetObject销毁时崩溃问题排查

问题描述

在Unreal Engine项目中使用AWS C++ SDK访问S3存储桶,SDK已通过Aws::Utils::Memory::MemorySystemInterface接入Unreal的内存分配器。当指定响应流类型的GetObject请求超出作用域销毁时,在Aws::Delete()中触发段错误。

请求代码如下:

Aws::S3::Model::GetObjectRequest request;
request.SetBucket(bucket);
request.SetKey(filename);
request.SetResponseStreamFactory([destination_file]() 
{return Aws::New<Aws::FStream>("getdata", destination_file, std::ios_base::out | std::ios_base::binary); }); 
// 怀疑此代码行引发问题

Aws::S3::Model::GetObjectOutcome outcome = s3.GetObject(request);
if (!outcome.IsSuccess())
{
    Completed.Broadcast(fullpath, false);
    return;
}
else 
{
    fullpath = to_file;
    Completed.Broadcast(fullpath, true);
    return;
}
// request和outcome在此处离开作用域,触发异常

请求执行成功(outcome.IsSuccess()为true)且文件已正确生成,但当outcome或request离开作用域时崩溃,错误信息:

Exception thrown at 0x00007FFA0CC2612A (vcruntime140.dll) in UnrealEditor.exe: 
0xC0000005: Access violation reading location 0x0000000000000068.

调用栈:

vcruntime140.dll!00007ffa0cc2612a() Unknown
    [Inline Frame] aws-cpp-sdk-core.dll!Aws::Delete(std::basic_iostream<char,std::char_traits<char>> * pointerToT) Line 117 C++
    aws-cpp-sdk-core.dll!Aws::Utils::Stream::ResponseStream::ReleaseStream() Line 62    C++
    aws-cpp-sdk-core.dll!Aws::Utils::Stream::ResponseStream::~ResponseStream() Line 54  C++
    UnrealEditor-Plugin.dll!UPlugin::Activate() Line 56 C++

异常触发于AwsMemory.h中的代码:

template<typename T>
    typename std::enable_if<std::is_polymorphic<T>::value>::type Delete(T* pointerToT)
    {
        if (pointerToT == nullptr)
        {
            return;
        }
        // deal with deleting objects that implement multiple interfaces
        // see casting to pointer to void in http://en.cppreference.com/w/cpp/language/dynamic_cast
        // https://stackoverflow.com/questions/8123776/are-there-practical-uses-for-dynamic-casting-to-void-pointer
        // NOTE: on some compilers, calling the destructor before doing the dynamic_cast affects how calculation of
        // the address of the most derived class.
        void* mostDerivedT = dynamic_cast<void*>(pointerToT); // <-- exception
        pointerToT->~T();
        Free(mostDerivedT);
    }

ReleaseStream()和ResponseStream()是Aws::Delete的包装,ReleaseStream会先刷新流再调用Delete。无迹象表明pointerToT在dynamic_cast前失效,但实际出现问题。所有操作在单线程执行,且已验证destination_file等本地变量有效。项目中其他未指定流工厂的S3请求(List、Put、Get)均正常。

问题原因及解决方案

核心原因

问题根源是跨模块内存管理与多态对象的不兼容:

  1. 通过Aws::New<Aws::FStream>创建流对象时,使用的是绑定到Unreal的内存分配器,分配的内存属于Unreal模块(UnrealEditor.exe或插件dll);
  2. Aws::FStream是AWS SDK定义的多态类,其虚函数表(vtable)由aws-cpp-sdk-core.dll维护;
  3. 当SDK执行dynamic_cast<void*>(pointerToT)时,需要读取对象的vtable来定位最派生类的内存地址,但此时Unreal的内存分配器可能已经将该内存块标记为释放或复用,导致访问非法地址0x68(通常是vtable偏移后的无效内存位置)。

其他未指定流工厂的请求正常,是因为这些请求使用SDK内部默认的流实现,内存分配与释放都在SDK模块内完成,不存在跨模块的多态对象销毁问题。

解决方案

  1. 改用Unreal原生文件流包装AWS响应流:
    避免直接使用Aws::FStream,转而用Unreal的文件系统接口创建写句柄,再包装成AWS兼容的响应流,确保内存管理在同一模块内完成:
    request.SetResponseStreamFactory([destination_file]() {
        FString unrealDestPath = FString(destination_file.c_str());
        IFileHandle* fileHandle = IFileManager::Get().CreateFileWriter(*unrealDestPath, FILEWRITE_BINARY);
        if (!fileHandle)
        {
            return nullptr;
        }
        // 使用PreallocatedStreamBuf包装Unreal文件句柄,自定义销毁逻辑
        return Aws::New<Aws::Utils::Stream::PreallocatedStreamBuf>(
            "S3ResponseStream",
            reinterpret_cast<Aws::Utils::Stream::PreallocatedStreamBuf::UnderlyingBufferType>(fileHandle->GetNativeHandle()),
            0, // 无需预分配缓冲区,直接写入文件
            [fileHandle](Aws::Utils::Stream::PreallocatedStreamBuf::UnderlyingBufferType) {
                delete fileHandle;
            }
        );
    });
    
  2. 确保内存分配释放的模块一致性:
    如果必须使用Aws::FStream,则需要临时切换回SDK默认的内存分配器创建对象,销毁时也使用SDK的分配器,但这种方式会破坏Unreal的内存跟踪机制,不推荐在正式项目中使用。
  3. 升级AWS SDK版本:
    部分旧版本AWS C++ SDK在跨模块多态对象销毁时存在bug,升级到最新稳定版可能修复该问题。

内容的提问来源于stack exchange,提问作者Soren Saville Scott

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 19:05:18