2013-03-13 4 views
0

최근 거대한 라이브러리를 ARC로 마이그레이션했으며 도구가 필요없는 섹션에서 두통이 발생했습니다. 여기에 코드입니다 : 이것은 꽤 똑바로 앞으로, 그러나, passwordData 객체가 overreleased되고있다한다Toll-Bridge overrelease

+ (NSString *)getKeychainItem:(NSString *)identifier 
{ 
    NSString *fullIdentifier = [NSString stringWithFormat:@"%@%@", kIdentifierPrefix, identifier]; 

    NSMutableDictionary *queryKeychain; 
    OSStatus status = noErr; 

    queryKeychain = [NSMutableDictionary dictionary]; 

    // Set the public key query dictionary. 
    [queryKeychain setObject:(__bridge id)kSecClassGenericPassword 
         forKey:(__bridge id)kSecClass]; 

    // Get the key. 
    CFDataRef data; 
    CFDictionaryRef queryKeychainCF = (__bridge CFDictionaryRef)queryKeychain; 
    status = SecItemCopyMatching(queryKeychainCF, (CFTypeRef *)&data); 

    NSData *passwordData = (__bridge_transfer NSData *)data; 

    NSString *password; 

    if (status == noErr) 
    { 
     password = [[NSString alloc] initWithBytes:[passwordData bytes] 
              length:[passwordData length] 
              encoding:NSUTF8StringEncoding]; 

    } 
    else if (status != errSecItemNotFound) 
    { 
     NSLog(@"Error getting keychain item %@ -- OSStatus: %lu", identifier, status); 
    } 

    return password; 
} 

내가 스택 추적이 this 왜, 아무 생각이 없습니다. passwordDatanil으로 설정하고 __bridge__transfer을 수행하지 않으면 충돌이 발생하지 않습니다. 왜 어떤 아이디어?

고맙습니다.

답변

0

이 문제가 완전히 다른 개체에 있던 밝혀 소유권을 전송하지 않고 다리를

NSData *passwordData = (NSData *)data; 

를 사용하여 NSData 시도에 CFDataRef 캐스팅하거나 사용할 필요가 :

CFDictionaryRef queryKeychainCF = (__bridge_retained CFDictionaryRef)queryKeychain; 
status = SecItemCopyMatching(queryKeychainCF, (CFTypeRef *)&data); 
NSData *passwordData = (__bridge_transfer NSData *)data; 

A 모든 솔루션을 시도해보고 ARC에서 SecItemCopyMatching 메서드에 대한 읽기 오류를 시작하고 answer에 도착했습니다.

2

내가 __bridge_transfer에게 자신을 사용하지 않은,하지만 당신이에 "passwordData"로 변경하는 경우 :

NSData *passwordData = (NSData *)data; 

엑스 코드는 당신이 개 권장 사항을 제공합니다.

소유권을 이전하지 마십시오 (핵심 기반이 그것을 해제하는) :

NSData *passwordData = (NSData *)CFBridgingRelease(data); 

__bridge_transfer이 같은 일이 될 수도 있지만, 나는 ':

NSData *passwordData = (__bridge NSData *)data; 

소유권은 (ARC는 이상 소요) ve는 Xcode에서 권장하는 CFBridgingRelease 호출을 사용하는 데 문제가 없었습니다.

ARC가 메모리를 관리하지 않는 한 아무 것도 설정하지 않으면 실제로 아무 것도 해제되지 않습니다. 코어 파운데이션으로 명시 적으로 릴리즈하거나 소유권을 ARC로 옮기지 않는 한 Core Foundation 객체를 nil로 설정하지 않으려합니다.

반환 할 때 바로 CFRelease(data)을 사용하고 정상적인 __bridge을 사용하십시오.

이것은 모두 SecItemCopyMatching이 데이터 사본을 제공하고 릴리스하겠다는 것을 전제로합니다. NewCopy은 일반적으로 이것을 나타내는 키워드입니다. 서로 다른 지점에서 CFGetRetainCount(data)을 사용하여 추가로 디버그하여 카운트를 확인할 수 있습니다.

fullIdentifier가 사용되지 않는 것으로 나타났습니다. 이 모든 기능이 있습니까?

initWithBytes:length:encoding 대신 initWithData:encoding:을 사용할 수도 있습니다.

+0

'CFBridgingRelease'도 실패하는 것 같습니다 : http://i.imgur.com/8Wi4gB7.png.'SecItemCopyMatching'이 냄새를 맡았다 고 생각하기 시작했습니다. –

+0

정기적 인'__bridge'을하고 NSLog (@ "% d", CFGetRetainCount (data))를 여러 위치에 두어보십시오. NSString 메모리의 소유권을 가정 수 있습니다. – Luke

+0

감사합니다 루크,하지만 문제는 또 하나, SecItemCopyMatching 동작과 관련이 있습니다. –

0

는 올바른 코드를 부착,

NSData* passwordData = (__bridge NSData*) data;