Swift内存安全:长期写入访问冲突未报错?求触发报错示例
Great question! The example you tested is a case where older Swift compilers (like the one in Xcode 9.2) might not catch the access conflict because the overlapping access is too short-lived and straightforward. To reliably trigger a long-term access conflict that the compiler or runtime will flag, you need to create a scenario where a write access to a variable persists beyond the immediate function call, overlapping with subsequent read or write operations.
Here are two concrete examples that will trigger the error:
Example 1: Capturing an inout Parameter in a Closure
This example creates a long-lived write access by capturing the inout parameter in a closure that outlives the function call:
func makeIncrementer(for number: inout Int) -> () -> Void { // The closure captures a write access to `number` return { number += 1 } } var counter = 5 // The function returns, but the closure still holds a write access to `counter` let incrementCounter = makeIncrementer(for: &counter) // Attempting to modify `counter` directly creates a conflict counter = 10 // Compiler error: Simultaneous access to 'counter', but modification requires exclusive access incrementCounter()
The compiler will throw an error here because the closure incrementCounter maintains a long-term write access to counter, and trying to modify counter directly violates Swift's memory safety rules.
Example 2: Asynchronous Access to an inout Parameter
Using asynchronous operations extends the write access to the inout parameter beyond the function's execution, leading to a runtime conflict:
import Dispatch func asyncIncrement(_ number: inout Int) { DispatchQueue.global().async { // This access happens asynchronously, overlapping with external accesses number += 1 print("Incremented number: \(number)") } } var count = 0 asyncIncrement(&count) // Trying to modify `count` while the async operation holds access triggers a runtime error count = 1 // Runtime crash: Simultaneous accesses to 0x100000000, but modification requires exclusive access
In this case, the runtime will crash with a memory safety violation because the asynchronous closure still holds a write access to count when we try to modify it directly.
Why Your Original Example Didn't Trigger an Error
In your original code, the write access to stepSize inside increment(_:) is immediate and completes before any other access can occur. Older Swift compilers didn't detect this subtle overlapping access, but modern versions (Swift 5+) will actually flag this code with a warning or error. The key difference with the examples above is that they create long-lived accesses that persist beyond the function's immediate execution, making the conflict unambiguous to the compiler or runtime.
内容的提问来源于stack exchange,提问作者user509981

