如何修复 iOS 16 及更早版本动态链接器中的错误

iOS 16及以下的机型二次启动崩溃的问题,经过排查后发现是操作系统二次启动使用std::string没有重载ue operator delete。想问下有没有什么比较好的解决方案?

重现步骤

Hi,

你们应该是MallocBinned的分配器吧,有客户用了如下做法,你可以试试,如果不行,我们再继续沟通。

给UE定义的内存分配函数在iOS平台下都加上__attribute__((weak))的属性标签:​

#if PLATFORM_IOS
#define WEAK_SYM __attribute__((weak))
#else
#define WEAK_SYM
#endif
 
#if !FORCE_ANSI_ALLOCATOR
#define REPLACEMENT_OPERATOR_NEW_AND_DELETE \
    OPERATOR_NEW_MSVC_PRAGMA void* WEAK_SYM operator new  ( size_t Size                        ) OPERATOR_NEW_THROW_SPEC      { return FMemory::Malloc( Size ); } \
    OPERATOR_NEW_MSVC_PRAGMA void* WEAK_SYM operator new[]( size_t Size                        ) OPERATOR_NEW_THROW_SPEC      { return FMemory::Malloc( Size ); } \
    OPERATOR_NEW_MSVC_PRAGMA void* WEAK_SYM operator new  ( size_t Size, const std::nothrow_t& ) OPERATOR_NEW_NOTHROW_SPEC    { return FMemory::Malloc( Size ); } \
    OPERATOR_NEW_MSVC_PRAGMA void* WEAK_SYM operator new[]( size_t Size, const std::nothrow_t& ) OPERATOR_NEW_NOTHROW_SPEC    { return FMemory::Malloc( Size ); } \
    void WEAK_SYM operator delete  ( void* Ptr )                                                 OPERATOR_DELETE_THROW_SPEC   { FMemory::Free( Ptr ); } \
    void WEAK_SYM operator delete[]( void* Ptr )                                                 OPERATOR_DELETE_THROW_SPEC   { FMemory::Free( Ptr ); } \
    void WEAK_SYM operator delete  ( void* Ptr, const std::nothrow_t& )                          OPERATOR_DELETE_NOTHROW_SPEC { FMemory::Free( Ptr ); } \
    void WEAK_SYM operator delete[]( void* Ptr, const std::nothrow_t& )                          OPERATOR_DELETE_NOTHROW_SPEC { FMemory::Free( Ptr ); } \
    void WEAK_SYM operator delete  ( void* Ptr, size_t Size )                                    OPERATOR_DELETE_THROW_SPEC   { FMemory::Free( Ptr ); } \
    void WEAK_SYM operator delete[]( void* Ptr, size_t Size )                                    OPERATOR_DELETE_THROW_SPEC   { FMemory::Free( Ptr ); } \
    void WEAK_SYM operator delete  ( void* Ptr, size_t Size, const std::nothrow_t& )             OPERATOR_DELETE_NOTHROW_SPEC { FMemory::Free( Ptr ); } \
    void WEAK_SYM operator delete[]( void* Ptr, size_t Size, const std::nothrow_t& )             OPERATOR_DELETE_NOTHROW_SPEC { FMemory::Free( Ptr ); }
#else
    #define REPLACEMENT_OPERATOR_NEW_AND_DELETE
#endif

嗯嗯,我们用的是Binned1

感谢大佬~ 我先试一下,过几天给您反馈~~​

Hi, 请问改动有效果吗?

尝试着修改了ModuleBoilerplate.h中的宏定义,但是还是有同样的崩溃出现。现在正在尝试其他解决方案,还没有进展~

这里是这样的吗?

[Image Removed]

是这样的:

string StripArguments = BinaryLinkEnvironment.bIsBuildingDLL ? “-x” : “”;

我们没修改过这部分逻辑

麻烦改成 string StripArguments = “-x”; 试一下

好滴好滴~ 我试试

请问这个改动有效果吗?

我们这边还在测试,有结果了第一时间给您回复~

哈喽~ 这边试了下,还是有类似问题存在😭

之前有尝试过修改成Ansi内存分配,不会再发生崩溃了​。但是使用Ansi意味着更大的性能开销,我们评估下来最好还是不要这么搞。想问下大佬还有没有其他可以用到的办法

顺便附上了部分崩溃堆栈,请大佬过目~

1 libsystem_kernel.dylib 0x0000000214bcf674 __pthread_kill + 8

2 libsystem_pthread.dylib 0x00000002253331a8 pthread_kill + 268

3 libsystem_c.dylib 0x00000001de730c88 abort + 180

4 libsystem_malloc.dylib 0x00000001e55bbe28 _malloc_vreport + 904

5 libsystem_malloc.dylib 0x00000001e55bc00c _malloc_report + 60

6 libsystem_malloc.dylib 0x00000001e55b7914 _find_zone_and_free + 304

7 libc++.1.dylib 0x00000001e576d2f0 std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>::__grow_by_and_replace(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, char const*) + 256

8 libc++.1.dylib 0x00000001e576e0a4 std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>::append(char const*, unsigned long) + 112

Hi,

我们好像针对这种情况在ue5里做了fix,你先参考一下,合入应该不太麻烦

https://github.com/EpicGames/UnrealEngine/commit/bfa10b2f1ee699ea6b301adc9380bfb4078c8455

okk收到~ 我马上试一下~~

但是我们现在用的是4.26,看了下代码感觉区别还挺大的QAQ,很多函数甚至都搜不到,不知从什么地方开始改

想问下有没有适配4.26的逻辑呢~~

我试一下,看看能不能合入到4.27里。

可以试试这个改动先,我再找原作者确认一下有没有遗漏的地方。

好滴好滴,我先试试,感谢大佬~👏