Mobile Development 14 min read

Analyzing ARC Multithreaded Assignment Crashes in iOS Applications

This article examines how ARC‑managed object assignments can produce wild pointers and EXC_BAD_ACCESS crashes in multithreaded iOS apps, explains the underlying reference‑counting steps, demonstrates reproducible demo scenarios, and offers practical mitigation strategies for developers.

ByteDance Terminal Technology
ByteDance Terminal Technology
ByteDance Terminal Technology
Analyzing ARC Multithreaded Assignment Crashes in iOS Applications

1. Principle

In Objective‑C, assigning an object involves creating a new value, retaining the old value, loading the new value, and releasing the old value. Under ARC the compiler automatically inserts retain and release calls, as illustrated by the following code:

NSObject *_instance;
void foo(void) {
    _instance = [[NSObject alloc] init];
}

The release step can decrement the reference count to zero while another thread is still accessing the object, leading to a dangling pointer.

2. Crash Scenarios

A minimal demo shows three threads (A, B, C) interacting with _instance . Thread A creates the object, B and C read it, B releases it (reference count becomes zero), and C later accesses the already‑destroyed object, causing an EXC_BAD_ACCESS crash.

The reproduction steps are controlled with LLDB thread continue to let only one thread run at a time while the others remain paused.

3. Crash Causes

The crash occurs when the CPU executes an instruction such as ldr x17, [x2, #0x20] that reads the bits field of the object's class structure. After the object is released, the ISA pointer becomes a random value, making the calculated address illegal and triggering the exception.

4. Additional Crash Scenarios

4.1 Crash in objc_retain

If an object is passed as a parameter to a function, ARC retains it at entry. If the object has already been destroyed by another thread, the retain itself crashes.

4.2 Crash in objc_msgSend

Sending a message (e.g., isEqual: ) to a deallocated object causes the runtime to read the class cache via an instruction like ldr x11, [x16, #0x10] . A corrupted class pointer leads to an illegal memory access.

4.3 Crash in objc_autoreleasePoolPop

Objects created without the new/alloc/copy/mutableCopy prefix may be placed in an autorelease pool. When the pool is popped, objc_release is invoked; if the object was already freed, a crash occurs.

4.4 EXC_BREAKPOINT Crash

Pointer authentication instructions can compare a cleaned pointer with a corrupted one, causing a breakpoint exception when the values differ.

5. Typical Business Scenarios

5.1 Global Variable Assignment

Multiple threads simultaneously initialize a global variable (e.g., geckoSettingDict ) without proper synchronization, leading to premature deallocation and crashes. The fix is to use dispatch_once for one‑time initialization.

5.2 Property Assignment

Properties exposed to external callers (e.g., extraParam or autoResolutionParams ) are updated from several threads, causing over‑release. Using atomic or guarding updates with dispatch_once mitigates the issue.

5.3 Lazy‑Loaded Property

Lazy‑loaded properties (e.g., _interceptUrls , _userCache ) may be initialized from multiple threads, resulting in race‑condition deallocation. Initializing such properties in init or protecting the lazy‑load with a lock prevents the problem.

6. Summary

Although the underlying cause—over‑release of an object during ARC assignment—is simple, it is hard to detect in large apps with many threads and copied code. Understanding the ARC semantics, common crash patterns, and applying synchronization (e.g., dispatch_once , atomic properties) are essential for building robust iOS code.

debuggingiOSMemory ManagementmultithreadingcrashARCobjc
ByteDance Terminal Technology
Written by

ByteDance Terminal Technology

Official account of ByteDance Terminal Technology, sharing technical insights and team updates.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.