-[NSString stringWithCString:encoding:] memory management question
-[NSString stringWithCString:encoding:] memory management question
- Subject: -[NSString stringWithCString:encoding:] memory management question
- From: "Hank Heijink (Mailinglists)" <email@hidden>
- Date: Wed, 11 Nov 2009 14:58:58 -0500
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;
// 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];
[key release];
[contents release];
}
free(pBuffer);
}
_metaData = [[NSDictionary alloc] initWithDictionary:tempDict];
[tempDict release];
The code runs as part of an -init method, and sets the _metaData
instance variable (it's an NSDictionary *) of the class in question.
Most of the time, but not always, the last line ([tempDict release])
crashes with the following stack backtrace (MyApp, MyFile, etc. do
have better names than that):
Exception Type: EXC_BAD_ACCESS (SIGBUS)
Exception Codes: KERN_PROTECTION_FAILURE at 0x0000000000000005
Crashed Thread: 0
Application Specific Information:
iPhone Simulator 3.1 (139.1), iPhone OS 3.0 (7A341)
Thread 0 Crashed:
0 CoreFoundation 0x302042c0 CFRelease + 96
1 CoreFoundation 0x30227249
__CFDictionaryDeallocate + 281
2 CoreFoundation 0x30204421 _CFRelease + 241
3 MyApp 0x00004ca0 -[MyFile
getMetaDataFromFileHandle:] + 859 (MyFile.m:247)
4 MyApp 0x000042fd -[MyFile initWithPath:] +
382 (MyFile.m:62)
5 MyApp 0x000026b4 -[MyAppDelegate
applicationDidFinishLaunching:] + 407 (MyAppDelegate.m:68)
6 UIKit 0x308f8ac3 -[UIApplication
_performInitializationWithURL:sourceBundleID:] + 500
7 UIKit 0x30901bf5 -[UIApplication
_runWithURL:sourceBundleID:] + 594
8 UIKit 0x308fef33 -[UIApplication
handleEvent:withNewEvent:] + 1532
9 UIKit 0x308fad82 -[UIApplication
sendEvent:] + 71
10 UIKit 0x309013e1
_UIApplicationHandleEvent + 4865
11 GraphicsServices 0x32046375 PurpleEventCallback +
1533
12 CoreFoundation 0x30245560 CFRunLoopRunSpecific +
3888
13 CoreFoundation 0x30244628 CFRunLoopRunInMode + 88
14 UIKit 0x308f930d -[UIApplication _run] +
611
15 UIKit 0x309021ee UIApplicationMain + 1157
16 MyApp 0x00002324 main + 102 (main.m:13)
17 MyApp 0x00002292 start + 54
Here's what I found:
1. If I use -[NSString initWithUTF8String:], the crash doesn't happen.
2. If I allocate pBuffer only once, outside of the loop, the crash
doesn't happen.
3. If I print out the memory ranges that pBuffer occupies, it seems
that the crash happens when one allocation of pBuffer overlaps another
one. If they start at the same address, it's no problem, but if they
start at different addresses and overlap, it's a problem. This is why
the app doesn't always crash: if the memory ranges don't happen to
overlap, all is well.
So, I'm curious about how -[NSString initWithCString:encoding:] works.
According to the documentation, it returns "An NSString object
initialized using the characters from nullTerminatedCString." Does
that mean it doesn't copy the bytes? Then what does it do? -[NSString
initWithUTF8String] explicitly states that it returns "An NSString
object initialized by copying the bytes from bytes."
Any insight is greatly appreciated!
Many thanks,
Hank
_______________________________________________
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