2009-06-29 5 views
3

私は本当にこれに困惑しています。私は正しい方法でメモリを管理していると信じていますが、コードを実行すると、オブジェクトを二重に解放していることが示唆されます。ここにコードを書いて、何が起こっているのかを説明します。二重放出が起こらないようにするとき

@protocol SomeDelegate <NSObject> 
@required 
- (id)initWithCols:(NSUInteger)Cols Rows:(NSUInteger)Rows; 
@end 


@interface SomeObject : NSObject <SomeDelegate> { 
} 
- (id)initWithCols:(NSUInteger)Cols Rows:(NSUInteger)Rows; 
@end 


@interface Layout : UIView { 
    id<SomeDelegate> someDelegate; 
} 
@property(retain) id<SomeDelegate> someDelegate; 
- (id)initWithFrame:(CGRect)aRect Cols:(NSUInteger)Cols Rows:(NSUInteger)Rows; 
@end 


@implementation Layout 
@synthesize someDelegate; 
- (id)initWithFrame:(CGRect)aRect Cols:(NSUInteger)Cols Rows:(NSUInteger)Rows { 

    if(self = [super initWithFrame:aRect]) { 
    cols = Cols; 
    rows = Rows; 
    id<SomeDelegate> delegate = [[SomeObject alloc] initWithCols:cols Rows:rows]; 
    [self setSomeDelegate:delegate]; 
    //[delegate release]; 
    } 
    return self; 
} 

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

@end 

ここで、「// [委任リリース];」のコメントを外すと、レイアウトクラスのコンストラクタの行に "EXC_BAD_ACCESS"というエラーが発生し、アプリケーションがdeallocを試みるとクラッシュします。レイアウトクラスのdeallocメソッドでsomeDelegateオブジェクトのリリースにクラッシュしました。コメントを残しておけば、アプリケーションは正常に動作します。

誰かがObjective-Cのメモリ管理について読んだことのすべてに反しているように見える理由を説明できますか?

コード例は実際には動作しますが、私のコードは例に従わないことに注意してください。私の実際のSomeObjectの中に、自動解放を引き起こしているものがありますか?

ありがとうございます。

+0

"デリゲート"変数の名前を変更するとどうなりますか?私はそれが問題ではないはずですが、私は同じ行に沿ってココア-deメーリングリストで何かを読んでいることを覚えています。特定の変数名で奇妙な振る舞いをする。 UIViewには独自のデリゲートがありますが、それに何か関係があるのだろうかと思います。 – dreamlax

+0

良い考えですが、残念なことに私は代理人に名前を変更しようとしましたが、まだリリースの問題があります。 –

+0

ちょっとメモしておきますが、コードスニペットが実際に機能するので、オートレットする原因となっているSomeObject(完全なコードでありスニペットではない)の中に何かがあると思っています。オブジェクトは、それを知らされることなく、自身を自動解放することができますか? –

答えて

3

まず、memory management rulesに戻って、デリゲートを他の場所で使用していることが明らかになっていないことを確認してください。

次に、NSZombieEnabledを有効にします(実行可能な設定の[引数]パネルで、環境変数NSZombieEnabledをYESに設定します)。

deallocメソッドがまだ存在しない場合は、[delalloc]を呼び出してください!)、そこにブレークポイントを置く - デリゲートが割り当て解除されたときに通知しますあなたが解放されているときにあなた。

また、コールスルー以外何もしない単純なリリース/自動解放メソッドを追加してから、それらをブレークポイントすると、いつリリースされるのかが正確に伝えられます。

三最終コメント:それはあるべき、つまり客観C/Cocoaのための標準的な命名規則では、あなたは、小文字のパラメータフィールドを持っている必要があります。

- (id)initWithFrame:(CGRect)aRect cols:(NSUInteger)Cols rows:(NSUInteger)Rows; 

あなたのIVARとプロパティが同じ名前されている場合、それは非常にあります

id<SomeDelegate> _someDelegate; 

@synthesize someDelegate = _someDelegate; 

:誤って間違ったものを使用するので、私はどちらか、混乱を避けるためにも、アップルとの混同を避けるために、Appleのよう_接頭辞、または他のいくつかの接頭辞を使用するために、異なるIVAR名とプロパティ名を使用することをお勧めするのは簡単そしてAppleは私たちを嫌うあなたのinitコードをする必要がありますので、初期化/ deallocを内セッター/ゲッターをINGの:

_someDelegate = [[SomeObject alloc] initWithCols:cols Rows:rows]; 
+0

NSZombieを有効にする方法については、こちらをご覧ください:http://stackoverflow.com/questions/5386160/how-to-enable-nszombie-in-xcode – madlymad

2

コメントに記載されているように、問題は掲載されたコードに含まれていないようです。

私はより多くの情報を求めることもできますが、私はティーチにしっかりと魚のキャンプに男だ....

-releaseでクラッシュが頻繁にそのさまざまな最適化で誤解を招くことになる - 末尾呼び出しの最適化一般的には、クラッシュしたように見せてくれるでしょう。クラッシュが発生したとき、本当に原因を特定するためにスタックに十分な情報がありません。

-releaseまたは-deallocにクラッシュがあると思われる場合は、ただちにゾンビをオンにします。これは、Instrumentsを介して、あるいは環境変数を介して、あるいはプログラムの実行の早い段階で財団の関数を呼び出すことによって行うことができます。

「ゾンビ」または「NSZombie」を開発環境に付属するドキュメント(「人間を釣る人を教える」のより多くのもの)で検索してください。

0

問題は、工場出荷時(自動解放)を介して作成されましたが、私はあまりにもリリースされたサブクラスで深いMutableArrayました。残念ながら、クラッシュは、継承されたdeallocがクラッシュを引き起こしていたことを示しておらず、最初にオーバーライドされたdeallocを停止しただけではありません。

ゾンビのことは、配列が原因だと言いましたが、他にはあまりありませんでした。私はNSZombieにはそれ以上のものがあり、それを最大限に活用するにはより多くの経験が必要だと思います。

関連する問題