2017-05-27 12 views
2

最近、私はXcodeのObjective Cメモリ管理で奇妙な動作に気付きました。 がエラーを生成する必要がありfirstStringのNSLogを解放した後ゼロポイントをsecondStringこと、Xcode 8.3の奇妙なClangの動作

#import <Foundation/Foundation.h> 

int main(int argc, const char * argv[]) { 
    @autoreleasepool { 
     NSString *firstString = [[NSString alloc] initWithString: @"Hello"]; 
     NSString *secondString = firstString; 
     [firstString release]; 
     NSLog(@"%@", secondString); 
    } 
    return 0; 
} 

私は思う: は、ここでは、コードです。 しかし、このコードはエラーを生成せず、 "Hello"文字列を正常に出力します。 はI手動でコンパイルし、実行コードなどのコマンドで、あまりにもすべてのエラーを気づいていません:

% clang -framework Foundation -fno-objc-arc main.m && ./a.out 

私はオンラインObjective-Cのコンパイラ(GCC)(http://rextester.com/l/objectivec_online_compiler)で、このコードをコンパイルしようとしましたが、エラーが発生しました。 何が間違っていますか? XcodeでARCサポートがオフになっています。 ありがとうございます。

答えて

2

あなたは(Xcodeのの「製品」メニューのXcodeでシフト + コマンド + B、または「分析」)静的解析を実行する場合、それはあなたがオブジェクトを参照しようとしていることを警告しますそれが解放された後:

static analysis

問題はマニュアル参照カウントコードで、オブジェクトを割り当て解除するには、あなたの参照が自動的にnilからない設定されていることです。したがって、手作業でnilこれらのポインタを使用しない限り、以前に割り当てが解除されていたオブジェクトへのポインタがぶら下がってしまうことになります。

スタティックアナライザは、この種の問題を識別するのに非常に優れています。私は移動する前に静的アナライザーからきれいな健康保険証を持っていることを確認することをお勧めします。

このような状況での第2の防衛線は、ゾンビランタイムデバッグオプションを有効にすることです。これにより、オブジェクトの割り当てが解除された後でオブジェクトとのやりとりを試みると報告されます。ゾンビは、Xcodeターゲットのスキームを編集するときに「診断」セクションで有効にすることができます。

残念なことに、通常のメモリ管理ルールに従わずに(文字列への参照を保持することができるため、そうでなければいつでも割り当てが解除されるとは限りません)NSStringを使用しています。

カスタムクラスを除いて、あなたに似た例を考えてみましょう:

#import <Foundation/Foundation.h> 

@interface MyObject: NSObject 
@end 
@implementation MyObject 
@end 

int main(int argc, const char * argv[]) { 
    @autoreleasepool { 
     MyObject *firstObject = [[MyObject alloc] init]; 
     MyObject *secondObject = firstObject; 
     [firstObject release]; 
     NSLog(@"%@", secondObject); 
    } 
    return 0; 
} 

あなたがゾンビでこれを実行した場合、あなたはと対話しようとしていることを示す、対応するエラーメッセージが表示されます割り当て解除インスタンス:

2017年5月27日08:19:18.154033から0700のMyApp [36888:7215135] *** - [MyObjectにisProxy]:メッセージ割り当て解除インスタンスに送信0x100303620

しかし、あなたはNSStringからこの警告を受け取っていないかもしれません。要するに、NSStringの動作からより広範なメモリ管理の結論を引き出さないようにすべきである。代わりに、Xcodeの静的アナライザーとゾンビに頼ってください。 (アプリのデバッグが完了したら、ゾンビを無効にしてください。)

+0

このような詳細な回答ありがとうございます!私は試して、他のオブジェクト(NSStringではない)で期待される動作を得ました。 – akozin

+0

'NSString'はこの動作に悪名高いです。私は非常に異常に行動する他の人には慣れていませんが、可能です。同じような問題を抱えている他のクラスを知らなくても、私はさらにコメントできません。しかし、静的アナライザーの助言に従えば、あなたは大丈夫でしょう。 – Rob