CFString memory leak

2019-08-14 17:13发布

I have narrowed down a memory leak to the following code

CFStringRef CFDataToString(CFDataRef data)
{
    UInt8* buf = malloc(CFDataGetLength(data));

    CFDataGetBytes(data, CFRangeMake(0, CFDataGetLength(data)), buf);

    CFMutableStringRef output = CFStringCreateMutable(kCFAllocatorDefault, CFDataGetLength(data) * 2);

    for(int i = 0; i < CFDataGetLength(data); i++) {
        CFStringAppendFormat(output, NULL, CFSTR("%02x"), buf[i]);
    }

    free(buf);
    CFRelease(data);

    return output;
}    

Below is the code used in context, some methods has been simplified for demonstration. Instruments is reporting a memory leak of CFStringCreateMutable and CFStringAppendFormat.

CFStringRef CFDataToString(CFDataRef data)
{
    UInt8* buf = malloc(CFDataGetLength(data));

    CFDataGetBytes(data, CFRangeMake(0, CFDataGetLength(data)), buf);

    CFMutableStringRef output = CFStringCreateMutable(kCFAllocatorDefault, CFDataGetLength(data) * 2);

    for(int i = 0; i < CFDataGetLength(data); i++) {
        CFStringAppendFormat(output, NULL, CFSTR("%02x"), buf[i]);
    }

    free(buf);
    CFRelease(data);

    return output;
}    

CFDataRef hmac(CFStringRef key, CFStringRef data)
{
    const char *cKey  = CFStringGetCStringPtr(key, CFStringGetSystemEncoding());
    const char *cData = CFStringGetCStringPtr(data, CFStringGetSystemEncoding());
    unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH];

    CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
    CFDataRef HMAC = CFDataCreate(kCFAllocatorDefault, cHMAC, sizeof(cHMAC));

    return HMAC;
}

CFDictionaryRef buildRequest(CFMutableDictionaryRef params)
{
    CFMutableStringRef signature = CFStringCreateMutable(NULL, 0);
    CFStringAppend(signature, CFDataToString(hmac(CFSTR("mykey"), CFSTR("mydata"))));

    CFDictionarySetValue(params, CFSTR("signature"), signature);


    // ....
    // ....       


    return params;
}

void request(CFMutableDictionaryRef params)
{
    params = buildRequest(params);

    // ... Run request

    CFRelease(params);
}

Instruments output...

enter image description here

enter image description here

1条回答
ら.Afraid
2楼-- · 2019-08-14 17:37

Just once more as answer.

All data allocated with a Create method puts the responsibility for releasing the data to the programmer. In this regard, it's the same as calling malloc. No method will ever release this data, unless explicitely stated in the documentation.

To solve your problem, save a reference to the 'Created' (Allocated) data in the method which receives it and release it at the end of the method, once you're done with it.

查看更多
登录 后发表回答