Назначение из метода Class связывает класс вместо его возвращаемого значения
Я заметил что-то странное в поведении кода, который я сейчас пишу, и подумал, что я попрошу здесь посмотреть, не делаю ли я что-нибудь глупое, что может привести к этому.
По сути, когда я присваиваю переменную возвращаемому значению моего метода класса, вместо переменной, содержащей ссылку на возвращаемое значение, она содержит ссылку на класс. Смотрите код ниже:
NSArray * newAddresses = [MyHost addressesForHostname: @"google.com"];
Который имеет сигнатуру метода
+ (NSArray *) addressesForHostname: (NSString *)hostname
И возвращает
return (__bridge_transfer NSArray *) ipAddresses; // ipAddresses is a CFMutableArrayRef
Как видите, я использую бесплатное мостовое соединение для использования объектов CoreFoundation, так как собираю список IP-адресов для некоторых сетевых интерфейсов.
После newAddresses
был назначен, я смотрю на класс newAddresses
массив в LLDB и получить:
(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;
}
1 ответ
Итак, я нашел решение, и оно лежит во мне, забыв инициализировать ipAddresses = nil
прежде чем что-то случится. Как написан этот код, он не будет присваивать значение ipAddresses
если он не может решить hostRef
дано CFHostStartInfoResolution
, Без значения в ipAddresses
, он возвращает неинициализированный указатель, который был приведен и передан его владельцу.
Я не могу найти официальную документацию, в которой говорится об этом, но я считаю, что это будет неопределенное поведение.
Я должен заявить, что если кто-то использует этот код в качестве ссылки, у меня возникают противоречивые сбои на линии, где я выпускаю hostRef
, Это не связано с проблемой, которую я создал для этой темы, но на нее стоит обратить внимание.