我正在使用此类的实例将必要的值传递给发送套接字数据的函数:
@interface SsdpParameters : NSObject
{
CFDataRef msg;
CFDataRef addr;
CFSocketRef sock;
}
@property CFDataRef msg;
@property CFDataRef addr;
@property CFSocketRef sock;
@end
这是负责发送套接字数据的函数:
-(void)SendSsdpResponse:(id)parameters
{
SsdpParameters *params = parameters;
CFDataRef msg = (CFDataRef)params.msg;
CFDataRef addr = (CFDataRef)params.addr;
CFSocketRef sock = (CFSocketRef)params.sock;
CFSocketError err = CFSocketSendData (sock, addr, msg, 0); // Program received signal: "EXC_BAD_ACCESS".
if (err)
{
NSLog(@"Error sending Valid Response");
}
}
此函数设置套接字并在1秒延迟后调用SendSsdpResponse:
- (void) sendValidResponses
{
NSMutableString *message = nil;
CFSocketRef sock = [self newSSDPSendSocket];
if(sock != nil)
{
struct sockaddr_in SSDPaddr;
memset(&SSDPaddr, 0, sizeof(SSDPaddr));
SSDPaddr.sin_family=AF_INET;
SSDPaddr.sin_addr.s_addr=inet_addr(SSDP_ADDRESS);
SSDPaddr.sin_port=htons(SSDP_PORT);
// Loop through list, sending SSDP
for (NSString *aKey in list)
{
message = [[NSMutableString alloc] initWithString:@"NOTIFY * HTTP/1.1\r\n"];
// Append more lines to message.
CFDataRef addr = CFDataCreate(NULL, (const UInt8*)&SSDPaddr, sizeof(SSDPaddr));
CFDataRef msg = CFDataCreate(NULL, (const UInt8*)[message UTF8String], [message lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
SsdpParameters *parameters = [[SsdpParameters alloc] init];
parameters.msg = msg;
parameters.addr = addr;
parameters.sock = sock;
[self performSelector:@selector(SendSsdpResponse:) withObject:parameters afterDelay:1.0];
CFRelease(addr);
CFRelease(msg);
[message release];
}
CFRelease(sock);
}
}
正如您在评论中看到的那样,在SendSsdpResponse中,我得到了一个" EXC_BAD_ACCESS"尝试调用CFSendSocketData时出错。我怀疑它是因为我正在"传递" sock
,addr
和msg
,运行时不喜欢这个。在将CF数据类型的变量传递给其他函数之前,我遇到过这个问题。我还没有找到答案,希望有人能在这里帮助我了解幕后发生的事情。
谢谢!
答案 0 :(得分:2)
EXC_BAD_ACCESS
错误通常表示您正在尝试在已经解除分配的实例上调用方法。如果您没有正确retain
个变量,通常会出现这种情况,尤其是当它们在函数之间传递时。
执行带延迟的选择器时,在此行:
[self performSelector:@selector(SendSsdpResponse:) withObject:parameters afterDelay:1.0];
您为方法提供了parameters
变量,该变量具有您提供的标头中定义的属性。问题是在performSelector:
方法之后,您正在释放引用addr
和msg
的内存。由于您正在延迟执行此选择器, addr和msg指向的内存在使用之前将被释放。
因此,一旦释放了这个内存,它就不再是SsdpParameters
对象中的“好”了。您应该(在这些属性的setter中,在SsdpParameters
对象上)复制此内存,以便原始调用者可以安全地释放它。
您应该调查此功能:
CFDataRef CFDataCreateCopy (
CFAllocatorRef allocator,
CFDataRef theData
);
然后,你的二传手看起来像:
@implementation SsdpParameters
...
- (void)setMsg:(CFDataRef)m {
// You should also release msg if it already exists
msg = CFDataCreateCopy(CFAllocatorGetDefault(), m);
}
...
@end
答案 1 :(得分:0)
要进行问题排查,请尝试将呼叫替换为
[self performSelector:@selector(SendSsdpResponse:) withObject:parameters afterDelay:1.0];
立即致电
[self SendSsdpResponse:parameters];
看看会发生什么。
如果仍然显示“EXC_BAD_ACCESS”,则表示您的参数设置不正确。另一方面,如果没有出现错误,则表示参数对象最初是正常的,但在延迟完成之前变为无效。例如,参数对象是保留还是复制“addr”和“msg”?