2

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

这是我认为是我的代码的相关部分,来自我创建的一个名为 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;
}

但是,如果我将变量名称从sockettosockbanana任何其他名称更改,代码运行良好,这让我很奇怪。为什么会这样?是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 回答