Objective c 为CFHostRef调用CFRelease有时会崩溃

Objective c 为CFHostRef调用CFRelease有时会崩溃,objective-c,core-foundation,Objective C,Core Foundation,这是我今天早些时候发表的一篇文章中提出的第二个问题。我有下面的方法,它可以满足我的需要,但有时在调用hostRef变量上的CFRelease时崩溃。我认为这可能与我试图释放它时在别处使用的资源有关,但据我所知,我正在同步解析主机,而不是从另一个线程访问它 在CFRelease之前,我尝试调用cfhostcancelinformalesolution,但这并没有改变崩溃的频率。我想我会把这篇文章贴在这里,看看是否有一些假设或误解是不正确的 + (NSArray *) addressesForHos

这是我今天早些时候发表的一篇文章中提出的第二个问题。我有下面的方法,它可以满足我的需要,但有时在调用
hostRef
变量上的
CFRelease
时崩溃。我认为这可能与我试图释放它时在别处使用的资源有关,但据我所知,我正在同步解析主机,而不是从另一个线程访问它

CFRelease
之前,我尝试调用
cfhostcancelinformalesolution
,但这并没有改变崩溃的频率。我想我会把这篇文章贴在这里,看看是否有一些假设或误解是不正确的

+ (NSArray *) addressesForHostname: (NSString *)hostname {

    CFMutableArrayRef ipAddresses = nil;

    DLog(@"Getting addresses for host name %@", hostname);

    CFHostRef hostRef = CFHostCreateWithName(kCFAllocatorDefault, (__bridge CFStringRef)(hostname));
    CFStreamError error;

    BOOL didResolve = CFHostStartInfoResolution(hostRef, kCFHostAddresses, &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 = NULL;
            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);

                    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);

                    break;
                }

                default:
                    DLog(@"Unsupported addressing protocol encountered. Gracefully ignoring and continuing.");
                    break;
            }

            if(ipAddress != NULL) {
                free(ipAddress);
            }
        }

        CFRelease(responseObjects);

    }

    CFRelease(hostRef);

    return (__bridge_transfer NSArray *) ipAddresses;
}
+(NSArray*)地址主机名:(NSString*)主机名{
CFMutableArrayRef ipAddresses=nil;
DLog(@“获取主机名%@的地址”,主机名);
CFHostRef hostRef=CFHostCreateWithName(kcfolocatordefault,(uu桥CFStringRef)(主机名));
cfr错误;
BOOL didrove=CFHostStartInfoResolution(hostRef、kcfhostaddress和error);//同步获取主机。
如果(didResolve){
CFArrayRef responseObjects=CFHostGetAddressing(hostRef,NULL);
long numberOfResponses=CFArrayGetCount(responseObjects);
IPAddresss=CFArrayCreateMutable(kCFAllocatorDefault、numberOfResponses和kCFTypeArrayCallBacks);
对于(int i=0;isa_系列){
案例AF_INET:{//Internetworking AKA IPV4
DLog(@“提取IPV4地址”);
*socketAddress=(struct sockaddr_in*)currentAddress中的struct sockaddr_;
ipAddress=malloc(sizeof(INET_ADDRSTRLEN));
inet_ntop(AF_inet,
&(socketAddress->sin_addr),
IP地址,
INET_ADDRSTRLEN);
CFStringRef ipAddressString=CFStringCreateWithCString(kCFAllocatorDefault,ipAddress,kCFStringEncodingASCII);
CFArrayInsertValueAtIndex(ipaddress,i,ipaddress字符串);
打破
}
案例6:{//IPV6
DLog(@“提取IPV6地址”);
结构sockaddr_in6*socketAddress=(结构sockaddr_in6*)当前地址;
ipAddress=malloc(sizeof(INET6_ADDRSTRLEN));
inet_ntop(AF_INET6,
&(socketAddress->sin6_addr),
IP地址,
INET6_ADDRSTRLEN);
CFStringRef ipAddressString=CFStringCreateWithCString(kCFAllocatorDefault,ipAddress,kCFStringEncodingASCII);
CFArrayInsertValueAtIndex(ipaddress,i,ipaddress字符串);
打破
}
违约:
DLog(@“遇到不支持的寻址协议。正常忽略并继续。”);
打破
}
如果(ipAddress!=NULL){
免费(IP地址);
}
}
CFRelease(响应对象);
}
CFRelease(hostRef);
返回(uu桥u传输协议*)IP地址;
}

删除
CFRelease(响应对象)应修复

,必须遵循核心基础对象的创建规则。如果通过调用名称中带有“创建”或“复制”字样的函数(或者如果显式调用CFRetain)来接收对象,则必须在处理完对象后释放(CFRelease)。如果没有以这种方式接收对象,则不能释放对象

您的代码中有几个错误。首先,您正在查找的对象,它位于
responseObjects
附近。您可以使用以下方法获取此对象:

CFDataRef responseObject = CFArrayGetValueAtIndex(responseObjects, i);
该函数的名称中没有“创建”或“复制”。您不能在其上调用
CFRelease

但是,您也将其称为:

ipAddresses = CFArrayCreateMutable(kCFAllocatorDefault, numberOfResponses, &kCFTypeArrayCallBacks);
在几个地方:

CFStringRef ipAddressString = CFStringCreateWithCString(kCFAllocatorDefault, ipAddress, kCFStringEncodingASCII);

您必须在这些对象超出范围之前调用
CFRelease
,否则您将泄漏它们。

我认为
CFStreamError错误可能导致此问题

是否尝试将错误声明为null

// synchronously get the host.
BOOL didResolve = CFHostStartInfoResolution(hostRef, kCFHostAddresses, NULL);

原因在于CoreFoundation的命名约定。文档中对此进行了描述。