2013-07-31 39 views
2

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

下面是我认为是我创建的名为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; 
} 

但是,如果我改变变量的名字从socketsockbanana或任何其他名称,代码运行正常,哪一种weirds我出去。为什么会发生?是socket某种保留的系统字?如果是这样的话,我会希望代码根本不能编译,但是我对Objective-C很新颖。

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

+2

没有编译器或连接器警告?我会期待一个。系统中有一个名为'socket()'的函数,我认为会有符号冲突。 – bbum

+0

不,完全没有警告(至少在我有什么警告设置,我没有从默认更改)。我想'socket()'解释它,但是 - 谢谢! – ekl

+0

嗯 - 我有点惊讶,你至少没有在运行时发出警告。奇。 – bbum

回答

1

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

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

  1. 声明变量是静态的。这会将变量的范围限制为该文件,以便GCDAsyncSocket不会意外解决它。无论如何,将它从全局命名空间中移除将是一个好主意。
  2. 使其成为私人成员变量。

把它改成一个私有成员变量,改变这种:

@implementation Socketmanager 
GCDAsyncSocket *socket; 

这样:

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

@implementation SocketManager 
...