2

ビルドの種類によってターゲット iOS 4 が変わる iPhone アプリケーションでクラッシュが発生することがわかりました。

デバッガーは私に先に進むことを何も与えていません。

 UIViewController *result = [self factory](self);

EXC_BAD_ACCESS で。selfNSObject を継承するクラスです (以下では NSObjectInheritor として示されています)。ゾンビが有効です。メソッドを 3 つの方法で変更してみましfactoryたが、次の結果が得られました。

これは、デバッグ ビルドとアドホック ビルドの両方でクラッシュします...

- (FactoryMethod) factory;
{
    return [^ UIViewController * (NSObjectInheritor *newThing)
    {
      return [[ViewControllerClass alloc] initWithStuff:(boolValue ? foo : bar)];
    } autorelease];
}

これはデバッグビルドでは機能しますが、アドホックでクラッシュします...

- (FactoryMethod) factory;
{
  return [^ UIViewController * (NSObjectInheritor *newThing)
  {
    if(boolValue)
    {
      return [[ViewControllerClass alloc] initWithStuff:foo];
    }
    else
    {
      return [[ViewControllerClass alloc] initWithStuff:bar];
    }
  } autorelease];
}

これはデバッグとアドホックの両方で機能しますが、非常に見苦しく冗長です。

- (FactoryMethod) factory;
{
  if(boolValue)
  {
    return [^ UIViewController * (NSObjectInheritor *newThing)
    {
      return [[ViewControllerClass alloc] initWithStuff:foo];
    } autorelease];
  }
  else
  {
    return [^ UIViewController * (NSObjectInheritor *newThing)
    {
      return [[[ViewControllerClass alloc] initWithStuff:bar];
    } autorelease];
  }
}

私の理論ではboolValue、返されたブロックが実行された時点でアクセスできなくなります。それは

@interface SubclassOfNSObjectInheritor : NSObjectInheritor
{
  BOOL boolValue;
}

@property (readonly) BOOL boolValue;

YESまたはNOもちろんSubclassOfNSObjectInheritorのinitで割り当てられます)および

@synthesize boolValue;

SubclassOfNSObjectInheritor の実装で。

最後の質問は、何が間違っているかについての私の理論は正しいですか? それを行う 3 番目の方法 (アドホック ビルドおよびデバッグ ビルドで動作することが示されています) は安全ですか? これを行う最善の方法は何ですか?

4

1 に答える 1

6

あなたの問題は2つあります.1つ目はブロックを過剰に解放していることと、2つ目はブロックがスタック上に作成されていることです。これは、メソッドが戻ると消えます(基本的に、以前に破棄されたスタックフレームにポインターを返しています)。

代わりに、ブロックをコピーして、戻る前に自動解放してください。copyこれは、メッセージを使用して Objective-C の方法で行うことができますBlock_copy()。関数を呼び出すことができます。

さまざまな構成でのクラッシュは、まったくの偶然です。したがって、実装の 1 つを修正するには、次のようにします。

- (FactoryMethod) factory;
{
  return [[^(NSObjectInheritor *newThing)
  {
    if(boolValue)
    {
      return [[ViewControllerClass alloc] initWithStuff:foo];
    }
    else
    {
      return [[ViewControllerClass alloc] initWithStuff:bar];
    }
  } copy] autorelease];
}
于 2010-07-01T02:17:24.847 に答える