2013-07-31 44 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 
...