我已经注意到我目前正在编写的代码行为中出现了一些奇怪的内容,并且我想在此问我是否会做一些会导致这种情况发生的愚蠢行为。
基本上,当我将一个变量赋给我的类方法的返回值时,而不是保存对返回值的引用的变量,它将持有对该类的引用。请参阅以下代码:
NSArray * newAddresses = [MyHost addressesForHostname: @"google.com"];
其方法签名为
+ (NSArray *) addressesForHostname: (NSString *)hostname
并返回
return (__bridge_transfer NSArray *) ipAddresses; // ipAddresses is a CFMutableArrayRef
正如您所看到的,我正在使用免费桥接来使用CoreFoundation对象,因为我正在收集某些网络接口的IP地址列表。
在分配newAddresses
之后,我会查看LLDB中newAddresses
数组的类并获取:
(lldb)po [newAddresses class]
MYHOST
我对我如何使用__bridge_transfer
的假设错了吗?用于弥补ipAddresses
的所有对象都是CFStringRefs
。
编辑:我被要求提供整个方法,所以在这里!
+ (NSArray *) addressesForHostname: (NSString *)hostname {
CFMutableArrayRef ipAddresses;
DLog(@"Getting addresses for host name %@", hostname);
CFHostRef hostRef = CFHostCreateWithName(kCFAllocatorDefault, (__bridge CFStringRef)(hostname));
CFStreamError error;
BOOL didResolve = CFHostStartInfoResolution(hostRef, kCFHostNames, &error); // synchronously get the host.
if (didResolve) {
CFArrayRef responseObjects = CFHostGetAddressing(hostRef, NULL);
long numberOfResponses = CFArrayGetCount(responseObjects);
ipAddresses = CFArrayCreateMutable(kCFAllocatorDefault, numberOfResponses, &kCFTypeArrayCallBacks);
for ( int i = 0 ; i < numberOfResponses; ++i ) {
char * ipAddress;
CFDataRef responseObject = CFArrayGetValueAtIndex(responseObjects, i);
struct sockaddr * currentAddress = (struct sockaddr *) CFDataGetBytePtr(responseObject); // Unwrap the CFData wrapper aound the sockaddr struct
switch (currentAddress->sa_family) {
case AF_INET: { // Internetworking AKA IPV4
DLog(@"Extracting IPV4 address");
struct sockaddr_in * socketAddress = (struct sockaddr_in *) currentAddress;
ipAddress = malloc(sizeof(INET_ADDRSTRLEN));
inet_ntop(AF_INET,
&(socketAddress->sin_addr),
ipAddress,
INET_ADDRSTRLEN);
CFStringRef ipAddressString = CFStringCreateWithCString(kCFAllocatorDefault, ipAddress, kCFStringEncodingASCII);
CFArrayInsertValueAtIndex(ipAddresses, i, ipAddressString);
free(ipAddress);
break;
}
case AF_INET6: { // IPV6
DLog(@"Extracting IPV6 address");
struct sockaddr_in6 * socketAddress = (struct sockaddr_in6 *) currentAddress;
ipAddress = malloc(sizeof(INET6_ADDRSTRLEN));
inet_ntop(AF_INET6,
&(socketAddress->sin6_addr),
ipAddress,
INET6_ADDRSTRLEN);
CFStringRef ipAddressString = CFStringCreateWithCString(kCFAllocatorDefault, ipAddress, kCFStringEncodingASCII);
CFArrayInsertValueAtIndex(ipAddresses, i, ipAddressString);
free(ipAddress);
break;
}
default:
DLog(@"Unsupported addressing protocol encountered. Gracefully ignoring and continuing.");
break;
}
}
CFRelease(responseObjects);
}
CFRelease(hostRef);
return (__bridge_transfer NSArray *) ipAddresses;
}
答案 0 :(得分:0)
所以我找到了解决方案,而且在发生任何事情之前忘记初始化ipAddresses = nil
。编写此代码的方式如果无法解析ipAddresses
给hostRef
,则不会为CFHostStartInfoResolution
分配值。如果ipAddresses
中没有值,则返回一个未初始化的指针,该指针将被转换并转移其所有权。
我找不到正式文档说明这一点,但我相信这将是未定义的行为。
我应该声明,如果有人使用此代码作为参考,我在发布hostRef
的行上遇到了不一致的崩溃。这与我为此线程创建的问题无关,但值得指出。