Post

Replies

Boosts

Views

Activity

Reply to Operator new/delete override only work for the first time for an iOS App on iOS16
After read the dyld's doc: PrebuiltLoaderSet Policy, I've found a tricky work around: Create a new framework, let's say we name it "Interposing", add it to project OverrideNew's "Frameworks, Libraries, and Embedded Content" in the "General" settings tab. Add a cpp file in this framework, and add the following code to it: #include <fcntl.h> #define DYLD_INTERPOSE(_replacement,_replacee) \ __attribute__((used)) static struct{ const void* replacement; const void* replacee; } _interpose_##_replacee \ __attribute__ ((section ("__DATA,__interpose"))) = { (const void*)(unsigned long)&_replacement, (const void*)(unsigned long)&_replacee }; static int my_open(const char* path, int flags, mode_t mode) { int value; value = open(path, flags, mode); return value; } DYLD_INTERPOSE(my_open, open) Run project OverrideNew again on device, and everytime operator new override works. I've read the post: An Apple Library Primer, and found: "Dynamic linker interposing is not documented as API. While it’s a useful technique for developer tools, do not use it in products you ship to end users.", so I guess this tricky way is still not recommended. In the end, I think the solution is either to raise the deployment target to iOS 17, or totally remove the usage of the std stuff in libc++1.dylib.
1w
Reply to Operator new/delete override only work for the first time for an iOS App on iOS16
First thanks for the reply. "Or does your real app embed a bunch of different frameworks, where you want your operator overrides to apply to them all?" Thanks for reminding, the problem is in libc++.1.dylib, the title should be "Operator new/delete override of libc++.1.dylib only works for the first time for an iOS app on iOS16". I've changed the test code: #include <os/log.h> #include <string> static bool needLog = false; void* operator new(size_t size) { void* ptr = malloc(size); if(needLog) { // Log to prove override new works os_log_error(OS_LOG_DEFAULT, "Overrided new called. ptr: %p\n", ptr); } return ptr; } void operator delete(void* ptr) noexcept { free(ptr); if(needLog) { // Log to prove override delete works os_log_error(OS_LOG_DEFAULT, "Overrided delete called. ptr: %p\n", ptr); } } void StringConstructTest(void) { needLog = true; os_log_error(OS_LOG_DEFAULT, "Enter StringConstructTest1\n"); { std::string str; // a long string will trigger memory allocation on heap str = "Hello world and this is a long string.\n"; os_log_error(OS_LOG_DEFAULT, "%{public}s\n", str.c_str()); } os_log_error(OS_LOG_DEFAULT, "Exit StringConstructTest1\n"); // newly added code: os_log_error(OS_LOG_DEFAULT, "Enter new int test\n"); { int* ptr = new int; delete ptr; } os_log_error(OS_LOG_DEFAULT, "Exit new int test\n"); needLog = false; } First launch on device, ths log is: Enter StringConstructTest1 Overrided new called. ptr: 0x281f2f450 Hello world and this is a long string. Overrided delete called. ptr: 0x281f2f450 Exit StringConstructTest1 Enter new int test Overrided new called. ptr: 0x281058070 Overrided delete called. ptr: 0x281058070 Exit new int test Second and subsequent launches on device, ths log is: Enter StringConstructTest1 Hello world and this is a long string. Exit StringConstructTest1 Enter new int test Overrided new called. ptr: 0x281058070 Overrided delete called. ptr: 0x281058070 Exit new int test On both of the first and second launch, the operator override for new int always works, but the operator override for str = "Hellow world and this is a long string.", which is "operator=" of std::string only works for the first time. The compiled code of new int is in the main executable, while the compiled code of "operator=" of std::string is in libc++.1.dylib. So new/delete override for libc++.1.dylib only works for the first time for an iOS app on iOS16. "Is that indicative of your real app?" Yes, the problem happens in our real project, which is an Unreal Engine4 game. Unreal Engine overrides the operator new/delete by default. The main Engine runtime code barely use std::string, but some third-party plugin code may use std::string, and we found that the memory allocated by std::string's "operator=" is not through the Unreal Engine's override of new(which will call the engine's memory allocator), on iOS16 device for the second and subsequent launches. So I report the issue and want to ask if is there a way to make operator new/delete override of libc++.1.dylib works every time on iOS16?
2w