2015-06-16 5 views
0

Это второстепенный вопрос, который возник из сообщения, которое я сделал сегодня сегодня. У меня есть метод ниже, который отлично работает для того, что мне нужно, но иногда сбой, когда я вызываю CFRelease в переменной hostRef. Я думаю, что это может быть связано с ресурсом, который используется в другом месте, когда я пытаюсь его выпустить, но насколько я могу судить, я синхронно разрешаю хост, и я не получаю доступ к нему из другого потока.Вызов CFRelease для CFHostRef иногда будет сбой

Я попытался позвонить CFHostCancelInfoResolution до CFRelease, но это не изменило частоту сбоев. Я думал, что отправлю это здесь, чтобы узнать, есть ли какие-то предположения или неправильные представления, которые у меня есть, которые не соответствуют действительности.

+ (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; 
} 

ответ

1

удаления CFRelease(responseObjects); должен исправить это

+1

Причина заключается в соглашениях об именах CoreFoundation. Он описан в документе [Руководство по программированию памяти для Core Foundation] (https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFMemoryMgmt/Concepts/Ownership.html). – JustSid

1

Вы должны следовать Создать правило для объектов ядра Foundation. Если вы получили объект, вызвав функцию со словами Create или Copy в своих именах (или если вы вызываете CFRetain явно), вы должны освободить (CFRelease) объект, когда вы закончите с ним. Если вы не получили объект таким образом, вы не должны отпускать объект.

В коде есть несколько ошибок. Сначала вы найдете то, что находится около responseObjects. Вы приобретаете этот объект, используя:

CFDataRef responseObject = CFArrayGetValueAtIndex(responseObjects, i); 

У функции нет имени или копии. Вы не должны называть CFRelease.

Однако, вы также называем это:

ipAddresses = CFArrayCreateMutable(kCFAllocatorDefault, numberOfResponses, &kCFTypeArrayCallBacks); 

и в нескольких местах:

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

Вы должны вызвать CFRelease на этих объектах, прежде чем они выходят из области видимости или просочится их ,

0

Я думаю, CFStreamError error; может вызвать эту проблему.

Постарайтесь объявить ошибку null?

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