2

iPhoneアプリケーションでスキャンビルドコードアナライザーを実行して問題をチェックするスクリプトをターミナルで実行しています。偶然にも、deallocメソッドでリリースされていないIBOutletivarが見つからないインスタンスが少なくとも1つあることに気づきました。

ターミナルから実行するコマンドの内容は次のとおりです。

#!/bin/sh
cd /Developer/svn/MyCompany/iPhone/MyApplication
scan-build -analyzer-check-dead-stores -analyzer-check-llvm-conventions -analyzer-check-objc-mem -analyzer-check-objc-methodsigs -analyzer-check-objc-missing-dealloc -analyzer-check-objc-unused-ivars -analyzer-check-security-syntactic --experimental-checks -k -V -o scan-reports xcodebuild -configuration Debug -sdk iphonesimulator4.2 clean build

最新バージョンのチェッカーにアップデートしたので、新しいバージョンのチェッカーがあるとは限りません。これが私のクラスの.hファイルの関連部分です:

@interface LoginWizardUsernameViewController : UIViewController <UITextFieldDelegate, GetUserExistsDidFinish> {

 IBOutlet UITextField *username;
 IBOutlet UIActivityIndicatorView *activityIndicatorView;

}

@property (nonatomic, retain) UITextField *username;
@property (nonatomic, retain) UIActivityIndicatorView *activityIndicatorView;

そして、ここに.mファイルの関連部分があります:

// lots o' code omitted here

@implementation LoginWizardUsernameViewController

@synthesize username;
@synthesize activityIndicatorView;

- (void)dealloc 
{
    [super dealloc];
}

ご覧のとおり、2つのIBOutletアイテムのリリースはありませんが、プロパティ定義に保持されているものとしてリストされていても、チェッカーは何らかの理由でこれを認識していません。奇妙なことに、他のクラスの.mファイルに移動して、deallocメソッドでリリースをコメント化すると、問題のスキャンの最後にscan-buildが喜んで警告します。この特定の状況について何が違うのか理解できません。

4

1 に答える 1

4

これはClang静的アナライザーのバグであり、別の問題を修正しようとしたことが原因です。

ソースコードに基づいて、Clang静的アナライザーは非ポインターivarまたはivarのみ-deallocを含むクラスのチェックをスキップします。IBOutlet

104   // Does the class contain any ivars that are pointers (or id<...>)?
105   // If not, skip the check entirely.
106   // NOTE: This is motivated by PR 2517:
107   //        http://llvm.org/bugs/show_bug.cgi?id=2517
108 
109  bool containsPointerIvar = false;
110  
111  for (ObjCInterfaceDecl::ivar_iterator I=ID->ivar_begin(), E=ID->ivar_end();
112       I!=E; ++I) {
113 
114    ObjCIvarDecl* ID = *I;
115    QualType T = ID->getType();
116 
117    if (!T->isObjCObjectPointerType() ||
118        ID->getAttr<IBOutletAttr>() || // Skip IBOutlets.
119        ID->getAttr<IBOutletCollectionAttr>()) // Skip IBOutletCollections.
120      continue;
121 
122    containsPointerIvar = true;
123    break;
124  }
125 
126  if (!containsPointerIvar)
127    return;

クラスにIBOutlet以外のプロパティを追加するだけで、正しく機能するのではないかと思います。

于 2010-12-21T15:34:20.483 に答える