After distributing a UE5 iOS app using Photorealistic 3D Tiles to the App Store or TestFlight, the app crashes immediately after launching.
It works fine with local builds (same build configuration as when distributed).
It also works fine in a project that excludes Photorealistic 3D Tiles and only has Cesium SunSky.
Could you give me some advice?
Crash logs
App crashes on CesiumAsync::CachingAssetAccessor::get
Sorry that your app is having trouble. I’m not sure why Google Photorealistic 3D Tiles would work in a local build but not from the app store. This behavior is happening on the exact same device, correct?
To help us troubleshoot, can you test how your app functions with Cesium World Terrain (instead of Google’s data)? That may help us infer what’s happening here.
Glad you were able to figure it out @ARAkasaka! Unfortunately, our team isn’t familiar with deploying to the app store, so the fix wasn’t immediately apparent. Thank you for letting us know about the solution!
Just an update on the best workaround here… FORCE_ANSI_ALLOCATOR may not work well in the latest UE versions, and even if it does it may have unintended consequences (such as a reduction in performance).
Instead, I now recommend that you make a change to a script in the Xcode project. If you open Intermediate/ProjectFiles/[project name] (IOS).xcodeproj/project.pbxproj, you’ll see a section like this:
ED01E0DF7686EEC1CE350CF9 /* Generate dsym for archive, and strip */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"\"$(CONFIGURATION_BUILD_DIR)/$(EXECUTABLE_PATH)\"",
);
name = "Generate dsym for archive, and strip";
outputPaths = (
"\"$(DWARF_DSYM_FOLDER_PATH)/$(DWARF_DSYM_FILE_NAME)\"",
);
runOnlyForDeploymentPostprocessing = 1;
shellPath = /bin/sh;
shellScript = "set -e\n\n# Run the wrapper dsym generator\n\"${UE_ENGINE_DIR}/Build/BatchFiles/Mac/GenerateUniversalDSYM.sh\" \"${CONFIGURATION_BUILD_DIR}/${EXECUTABLE_PATH}\" \"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}\"\nstrip -no_code_signature_warning -x -S -D \"${CONFIGURATION_BUILD_DIR}/${EXECUTABLE_PATH}\"\n\n# Remove any unused architectures from dylibs in the .app (param1) that don't match the executable (param2). Also error if a dylib is missing arches\n\"${UE_ENGINE_DIR}/Build/BatchFiles/Mac/ThinApp.sh\" \"${CONFIGURATION_BUILD_DIR}/${CONTENTS_FOLDER_PATH}\" \"${CONFIGURATION_BUILD_DIR}/${EXECUTABLE_PATH}\"";
};
The important part is buried on the shellScript line and looks like this:
In other words, add the -x -S options to the strip command.
Now, if you archive / deploy your game again, you should no longer see the crash. You might need to edit a source file to force it to produce a new binary and re-run this script.
The reason for the crash is that UnrealBuildTool is (incorrectly, in my opinion) stripping operator new and operator delete symbols from the packaged binary. This means that code inside your game executable will use Unreal’s custom memory allocator, but code outside your game executable will use the default allocator. Specifically, any allocations in the C++ standard library that do not get inlined will use the default allocator. The crash is caused by allocating memory with Unreal’s custom allocator and then freeing it with the default allocator. It’s easy to trigger this by constructing something as simple as a std::string.
By adding these command-line arguments to strip, we tell it to only strip debug and local symbols. Global symbols like operator new / delete are left intact, ensuring that the std::string constructor and destructor, as well as all similar memory allocations, go through Unreal’s custom allocator.
More details of the problem here for anyone interested:
I’m going to report this to Epic as a bug, but this workaround should work well in the meantime.
I have tested this in UE5.4 with Cesium for Unreal 2.10 & 2.13 and in both cases, this fix worked for me.
I have removed the “FORCE_ANSI_ALLOCATOR” fix as it does not seem to work in 5.4