GCDAsyncSocket连接失败 - 仅当套接字变量被称为“套接字”时。怎么了?

时间:2013-07-31 17:25:59

标签: objective-c cocoa sockets exc-bad-access cocoaasyncsocket

我遇到的问题比任何事情都更令人困惑。我正在尝试使用GCDAsyncSocket在Objective-C中建立套接字连接。当且仅当套接字变量被调用socket时,发送到我的GCDAsyncSocket的connectToHost消息才会失败并显示EXC_BAD_ACCESS。它确实不是问题,因为我很容易使用不同的变量名称,但我很好奇为什么会发生这种情况。

我认为这是我的代码的相关部分,来自我创建的一个名为SocketManager的类。大部分代码都来自GCDAsyncSocket intro。下面的代码在指定行显示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;
}

但是,如果我将变量名称从socket更改为sockbanana或任何其他名称,则代码运行正常,这让我很奇怪。为什么会这样? socket是某种保留的系统字吗?如果是这种情况,我希望代码根本不能编译,但我对Objective-C很新。

顺便说一句,我的didConnectToHost:委托方法很少被调用,我认为这是一个单独的问题,但据我所知,它可能是相关的。

1 个答案:

答案 0 :(得分:1)

正如@bburn所说,这是一个符号碰撞。 GCDAsyncSocket使用了一个BSD socket()函数。如果你看一下调试器中的EXC_BAD_ACCESS,你会发现它在尝试调用socket()时实际上是失败的,因为它正在将函数地址解析为你变量的函数地址。

除了重命名变量之外,你还可以做一些事情(我认为即使你也重命名这个变量,做这些事情也是个好主意):

  1. 将变量声明为静态。这会将变量的范围限制在该文件中,以便GCDAsyncSocket不会意外地解析它。无论如何,将它从全局命名空间中删除是个好主意。
  2. 将其设为私有成员变量。
  3. 要将其更改为私有成员变量,请更改:

    @implementation Socketmanager
    GCDAsyncSocket *socket;
    

    到此:

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