Xcodeの静的解析機能が便利だ

最近、Xcodeの静的解析機能が面白いので、iPhone開発時によく使うようになった。以前は別途インストールしたclang analyzerを使っていたけれど、今はXcodeの“Build and Analyze”メニューから呼び出せるので手軽だ。

この静的解析機能を使うと、興味深い指摘をしてくれるのでいろいろ試してみた。開発環境は下記の通り。

メモリリークの可能性

下記のコードを解析させると、「アナライザ結果」として"Potential leak of an object allocated on line ..."が指摘される。

- (NSString*)test1
{
    NSString *data = [[NSString alloc] initWithString:@"Hello"];	
    return data;
}

もちろん上記のコードだけではメモリリークは発生しないが、呼び出し側で確実にreleaseしておくことが必要であり、使い方によっては(つまり呼び出し側でreleaseを忘れたら)メモリリークの可能性がある。

実際、Appleガイドラインで”Object Ownership Policy"として示されている通り、この場合にはautoreleaseを送ってオーナシップを放棄してから返すのが望ましい。この方法ならメモリリークの可能性が減り、アナライザでの指摘も無くなる。

    NSString *data = [[[NSString alloc] initWithString:@"Hello"] autorelease];

iPhoneメモリリークを防ぐためのコードとして良く紹介される例だけど、こんな状況をビルド時点で実際に指摘してくれるのは便利だと思う。

Nullポインタアクセスの可能性

下記のコードを解析させると、「アナライザ結果」として"Field access results in a dereference of a null pointer (loaded from variable 'data')"が指摘される。

typedef struct Bar {
    char *str;
} bar;

- (void)test2:(bar*)data
{
    if(data == NULL){
        // ...
    }
    NSLog(@"String:%s", data->str);
}

もちろん、上記の断片的なコードだけでは引数dataが「NULLになり得る」のか、或いは「決してNULLにはならない」のか不明だが、NULLと比較する箇所を参照して「NULLの可能性有り」と判断したので警告を出しているようだ。実際、NULLとの比較を省いた下記のコードでは警告が出なくなってしまう。1行単位での検査でなく、あるまとまった範囲の処理を分析対象にしているらしい。

- (void)test2:(bar*)data
{
    NSLog(@"String:%s", data->str);
}

静的解析ツールは変な癖があったりして無用な指摘を出すことも少なくないのだけど、上記のような潜在的なミスを指摘してくれるのなら、かなり便利に使えるのではないかと思う。処理の流れが画面上の矢印で示されるので分かりやすく、指摘内容が直ぐに理解出来るのは嬉しいところだ。clangの静的解析機能については下記に詳しい説明が載っている。

なお、現在の開発環境ではビルドターゲットをSimulatorにしておくと"Analyzer skipped this file due to parse errors"というエラーが出て解析に失敗してしまうようだ。手元の環境では、ターゲットをDeviceに切り替えると解析に成功した。



関連