Local variable declared with static storage duration

ID

objectivec.correctness.static_local_variable

Severity

info

Remediation Complexity

medium

Remediation Risk

medium

Remediation Effort

medium

Resource

Concurrency

Language

Objective-C

Description

Reports a static variable declared inside a method or function body, where one instance is shared by every call. A static const constant is not reported, and neither is the dispatch_once singleton idiom - a dispatch_once_t token, or a static immediately followed by the dispatch_once call that initialises it. Declarations at file scope are out of scope for this rule.

Rationale

A static local looks like a local and is not one. It is shared mutable state with the lifetime of the process, and nothing synchronises it, so two threads entering the method at once race on it - and on iOS that is not hypothetical, because the method may well be reached from a dispatch_async block on one call and the main queue on the next. The same sharing breaks reentrancy on a single thread: a recursive call, or a delegate callback that comes back into the method while the first call is still on the stack, sees the earlier call’s half-updated value. It also makes the method untestable in isolation, since the state carries over from whatever ran before and no test can reset it.

The following code illustrates the pattern detected by this rule:

@implementation Accumulator
- (NSInteger)nextTicket {
    // FLAGGED: Local variable declared with static storage duration
    static NSInteger ticket = 0;
    ticket += 1;
    return ticket;
}
@end

Remediation

Make the state an explicit property of the object that owns it, or pass it in and return it out, so its lifetime and its owner are visible. Where the value really is process-wide and initialised once, wrap the initialisation in dispatch_once and expose it through a class method, which is both thread safe and greppable. A value that never changes should be static const, or a file-scope constant.

Configuration

This detector does not need any configuration.

© 2026 Xygeni. All rights reserved