2

私は何よりも困惑している問題を抱えています。GCDAsyncSocket を使用して Objective-C でソケット接続を確立しようとしています。ソケット変数が呼び出された場合にのみ、GCDAsyncSocket に送信された connectToHost メッセージが EXC_BAD_ACCESS で失敗しますsocket。別の変数名を使用するのは簡単なので、正確には問題ではありませんが、なぜそれが起こるのか興味があります。

これは、私が作成した SocketManager というクラスからの、私のコードの関連部分であると私が信じているものです。ほとんどのコードはGCDAsyncSocket のイントロから取られています。以下のコードは、示された行で EXC_BAD_ACCESS で失敗します。

#import "SocketManager.h"
#import "GCDAsyncSocket.h"

@implementation SocketManager

GCDAsyncSocket *socket;

-(id) init {
    self = [super init];

    socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];

    NSError *err = nil;

    // EXC_BAD_ACCESS happens at the line below
    if (![socket connectToHost:@"localhost" onPort:26400 error:&err]) NSLog(@"I goofed: %@", err);

    NSLog(@"just created socket");

    return self;
}

ただし、変数名をsockettosockまたはbananaその他の名前に変更すると、コードは正常に実行されます。なぜそれが起こるのでしょうか?socketある種の予約済みシステム ワードですか? その場合、コードがまったくコンパイルされないことが予想されますが、私は Objective-C にかなり慣れていません。

ちなみに、私のdidConnectToHost:デリゲート メソッドが呼び出されることはめったにありません。これは別の問題だと思いますが、私が知る限り、関連している可能性があります。

4

1 に答える 1

1

@bburn が示唆したように、これはシンボルの衝突です。GCDAsyncSocket が使用する BSD socket() 関数があります。デバッガーで EXC_BAD_ACCESS を見ると、関数アドレスを変数のアドレスに解決しているため、socket() を呼び出そうとすると実際に失敗していることがわかります。

変数の名前を変更する以外に、いくつかのことができます (変数の名前も変更する場合でも、これらのいずれかを実行することをお勧めします)。

  1. 変数が静的であることを宣言します。これにより、変数のスコープがそのファイルに限定されるため、GCDAsyncSocket によって誤って解決されることはありません。いずれにせよ、グローバル名前空間から削除することをお勧めします。
  2. プライベート メンバー変数にします。

プライベート メンバー変数に変更するには、次のように変更します。

@implementation Socketmanager
GCDAsyncSocket *socket;

これに:

@interface SocketManager()
{    
    GCDAsyncSocket *socket;
}
@end

@implementation SocketManager
...
于 2013-07-31T21:28:12.417 に答える