Re: -[NSString stringWithCString:encoding:] memory management question
Re: -[NSString stringWithCString:encoding:] memory management question
- Subject: Re: -[NSString stringWithCString:encoding:] memory management question
- From: Jeremy Pereira <email@hidden>
- Date: Thu, 12 Nov 2009 10:59:59 +0000
On 11 Nov 2009, at 19:58, Hank Heijink (Mailinglists) wrote:
> Hi all,
>
> I've run into a funny crash when using -[NSString stringWithCString:encoding:]. The code in question runs in the iPhone Simulator. I haven't found anything on the web about this, but I found out some things by experimenting. I have a workaround, but I'm curious what's going on. I'd be very interested to hear your thoughts on this - apologies for the lengthy post!
>
> This is the relevant piece of code - I'm sorry I can't post it in full (NDA prohibits):
>
> nTags = 15;
> unsigned long metadataTags[] = { /* fifteen tags defined in some library */ };
>
> NSMutableDictionary *tempDict = [[NSMutableDictionary alloc] initWithCapacity:nTags];
>
> for (NSUInteger i = 0; i < nTags; i++) {
> unsigned long pcLength = 0;
> if (getLengthOfMetaData(fileHandle, metadataTags[i], 0, &pcLength) != 0) continue;
Religious rant first:
The above line is an abomination in my opinion. What's wrong with
if (getLengthOfMetaData(fileHandle, metadataTags[i], 0, &pcLength) == 0) {
// rest of loop code
}
>
> // pcLength is now the required buffer size.
> // Fill the buffer with metadata (and make room for a \0)
> unsigned char *pBuffer = malloc(pcLength + 1);
>
> if (getMetadata(fileHandle, metadataTags[i], pBuffer, pcLength) == 0) {
> pBuffer[pcLength] = '\0';
>
> NSString *key = [[NSString alloc] initWithFormat:@"%d", metadataTags[i]];
> NSString *contents = [[NSString alloc] initWithCString:(const char *)pBuffer encoding:NSASCIIStringEncoding];
>
> [tempDict setValue:contents forKey:key];
I think this should be [tempDict setObject:contents forKey:key];
>
> [key release];
> [contents release];
> }
>
> free(pBuffer);
> }
>
> _metaData = [[NSDictionary alloc] initWithDictionary:tempDict];
> [tempDict release];
The other observation I would make is are you sure that getMetadata() completely fills your buffer from zero to pBuffer, because if it doesn't it could leave some garbage non ASCII bytes in it. This, in turn would cause initWithCString:encoding: to return nil when using the ASCII encoding. I would allocate the buffer like this:
pBuffer = (unsigned char*) calloc(pcLength + 1, sizeof(unsigned char));
which zeros the whole buffer. Thus copying any amount of non nul ASCII chars <= pcLength will automatically result in a C string.
______________________________________________________________________
This email has been scanned by the MessageLabs Email Security System.
For more information please visit http://www.messagelabs.com/email
______________________________________________________________________
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden