[Solved] iOS apps distributed to the App store crash

Problem

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

Project details

Sample project with only Photorealistic 3D tiles placed in the Blank template project.
I referred to this tutorial.
https://cesium.com/learn/unreal/unreal-photorealistic-3d-tiles/

Hardware & Software details

  • macOS Sonoma 14.2.1
  • iPhone 14 iOS 17.2.1
  • Xcode 15.2
  • UE 5.3.2
  • Cesium for unreal 2.2.0
1 Like

Hi @ARAkasaka,

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.

Hi @janine thanks for your response.

This behavior is happening on the exact same device, correct?

Yes, same device (iPhone14, iOS17).

To help us troubleshoot, can you test how your app functions with Cesium World Terrain (instead of Google’s data)?

Even in the case of the app that includes only Cesium World Terrain, similarly, only the distributed app crashed after launching.

I resolved this issue by forcing FMallocAnsi usage on iOS platform.

if (Target.Platform == UnrealTargetPlatform.IOS)
{
    GlobalDefinitions.Add("FORCE_ANSI_ALLOCATOR=1");
}

https://alyamkin.artstation.com/blog/9VEQ/ue4-ios-and-pointer-being-freed-was-not-allocated

1 Like

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:

strip -no_code_signature_warning -D \"${CONFIGURATION_BUILD_DIR}/${EXECUTABLE_PATH}\"

Change it to this:

strip -no_code_signature_warning -x -S -D \"${CONFIGURATION_BUILD_DIR}/${EXECUTABLE_PATH}\"

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.

1 Like

Thanks so much for this.

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

thanks
eric

1 Like