iOS多线程非安全访问整数变量的崩溃实例及相关咨询
Hey there, let's tackle your questions about thread-unsafe integer access on iOS—this is a super common pain point when dealing with multi-threaded code, so I'll break this down clearly for you.
1. Crash Types Caused by Non-Thread-Safe Integer Access
When multiple threads read/write a plain integer variable (like NSInteger, int, or Swift Int) without atomic protections, the most common direct crashes you'll see are:
- EXC_BAD_ACCESS (SIGSEGV/SIGBUS): This often happens when a "torn read" (partial value from a write operation interrupted by another thread) produces an invalid integer that's used as an array index, pointer offset, or memory address. For example, a 64-bit integer might have its 32 high bits from one write and 32 low bits from another, creating a value that points to invalid memory.
- EXC_ARITHMETIC (SIGFPE): Rare but possible if a torn integer value leads to an illegal arithmetic operation—like division by zero, or integer overflow that triggers a hardware exception (depends on compiler flags and CPU architecture).
- EXC_BAD_INSTRUCTION (SIGILL): An edge case from aggressive compiler optimizations. If multi-threaded interference corrupts the instruction sequence generated for the integer access, the CPU might try to execute an invalid instruction.
Note: Most non-thread-safe integer access leads to silent data corruption first, but crashes happen when that corrupted value is used in a dangerous context (like array indexing) that directly triggers an exception.
2. Reproducible Test Cases (Unit Tests & Demo Code)
To reliably trigger crashes from thread-unsafe integer access, you need to amplify the race condition with lots of threads, frequent operations, and a dangerous use of the corrupted value (like array indexing). Here are working examples:
Objective-C Unit Test
#import <XCTest/XCTest.h> @interface IntegerThreadSafetyTests : XCTestCase @property (nonatomic, assign) NSInteger unsafeCounter; @end @implementation IntegerThreadSafetyTests - (void)testUnsafeIntegerCrash { self.unsafeCounter = 0; const NSInteger threadCount = 60; dispatch_group_t group = dispatch_group_create(); for (NSInteger i = 0; i < threadCount; i++) { dispatch_group_enter(group); dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{ for (NSInteger j = 0; j < 150000; j++) { // Non-atomic read/write to trigger race conditions self.unsafeCounter += 1; NSInteger corruptedValue = self.unsafeCounter; // Use the corrupted value to trigger an array out-of-bounds crash static NSArray *tinyArray = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ tinyArray = @[@"foo", @"bar", @"baz"]; }); // When corruptedValue is torn, modulo can produce an invalid index NSString *unused = tinyArray[corruptedValue % tinyArray.count]; (void)unused; } dispatch_group_leave(group); }); } dispatch_group_wait(group, DISPATCH_TIME_FOREVER); } @end
Swift Unit Test
import XCTest class IntegerThreadSafetyTests: XCTestCase { private var unsafeCounter: Int = 0 func testUnsafeIntegerCrash() { unsafeCounter = 0 let threadCount = 60 let group = DispatchGroup() for _ in 0..<threadCount { group.enter() DispatchQueue.global(qos: .userInitiated).async { for _ in 0..<150000 { self.unsafeCounter += 1 let corruptedValue = self.unsafeCounter // Trigger array out-of-bounds with the corrupted value let tinyArray = ["foo", "bar", "baz"] let unused = tinyArray[corruptedValue % tinyArray.count] _ = unused } group.leave() } } group.wait() } }
Tips for Higher Crash Probability
- Increase thread count (60+ works well) and loop iterations (150k+)
- Add a tiny
usleep(1)inside the inner loop to widen the race window - Run the test on a physical device (simulators have different thread scheduling behavior)
3. Crash Log Keywords & Regex Patterns
To filter crash logs related to your unsafe integer access, use these patterns:
Key Crash Type Strings
EXC_BAD_ACCESS (SIGSEGV): Most common for array out-of-bounds crashes from torn integersEXC_ARITHMETIC (SIGFPE): For overflow or division crashes__NSArrayI objectAtIndexedSubscript:: Objective-C array subscript crash call stack entrySwift._ContiguousArrayStorage.subscript.get: Swift array subscript crash call stack entry
Regex Examples
- Match array out-of-bounds crashes linked to your integer variable:
EXC_BAD_ACCESS.*(__NSArrayI objectAtIndexedSubscript:|Swift._ContiguousArrayStorage.subscript.get).*unsafeCounter - Match crashes involving your integer property's setter/getter:
(\[.*setUnsafeCounter:|\[.*unsafeCounter]|IntegerThreadSafetyTests\.unsafeCounter\.(set|get)) - Match integer overflow-related crashes:
EXC_ARITHMETIC.*integer overflow
内容的提问来源于stack exchange,提问作者cbutton9

