views:

132

answers:

2

I have a custom object which conforms to NSCoding, since the object should be writable to disk on terminate. In this class I have various properties holding Cocoa object types such as NSStrings, NSArrays, NSDictionaries. One particular property is this one:

@property (readwrite, copy) NSArray  *artistReleases;

It's actually an Array which is supposed to hold some NSDictionaries. Those dictionaries are created within a class method which is responsible for parsing data from an XML file.

artist.artistReleases = [NSArray arrayWithArray:releases];

The error occurs when I try to save the property with my encoder:

[encoder encodeObject:artistReleases forKey:@"artistReleases"];

I'll get an EXC_BAD_ACCESS error. NSZombie tells me

*** -[CFString retain]: message sent to deallocated instance 0xd6f28fe0

...and I have absolutely no Idea where to look for this retain. malloc_history tells me:

ALLOC 0xd6f28fe0-0xd6f28fff [size=32]: thread_b0244000 |thread_start | 
_pthread_start | __NSThread__main__ | -[NSThread main] | 
-[SearchViewController invokeGetArtist:] | +[GetDetails getArtist:summary:theURL:] |
-[CXMLNode stringValue] | +[NSString stringWithUTF8String:]   | 
-[NSPlaceholderString initWithBytes:length:encoding:] | 
CFStringCreateWithBytes | __CFStringCreateImmutableFunnel3 |
_CFRuntimeCreateInstance | GMmalloc_zone_malloc_internal 

I have no concrete idea what to make of it. It does not make any sense to me. Maybe someone could point me in a certain direction by interpreting the malloc history.


EDIT

Here's the part where the property in question is populated. For the sake of bugfixing I out-commented some CXMLNode invocations and did not insert those here. This also means that there seems to be no error connected to those objects (until I try to access that data which is created with those methods). BTW, I Use TouchXML for XPath queries.

NSArray *releaseNodes;
releaseNodes = [root nodesForXPath:@"/pathToReleases" error:nil];
NSMutableArray *releases = [[NSMutableArray alloc] init];

for (CXMLElement *resultElement in releaseNodes) {
    if (resultElement != nil) {
        NSMutableDictionary *releaseElement = [[NSMutableDictionary alloc] init];

        for (int counter = 0; counter < [resultElement childCount]; counter++) {
            [releaseElement setObject:[[resultElement childAtIndex:counter] stringValue] forKey:[[resultElement childAtIndex:counter] name]];
        }
        [releases addObject:releaseElement];
        [releaseElement release];
    }
}
if ([releases count] == 0) 
    [releases addObject:[NSMutableDictionary dictionaryWithObject:@"-" forKey:@"title"]];
artist.artistReleases = [NSArray arrayWithArray:releases];

EDIT 2 I have narrowed down where the property in question looses its content. po'ing the property after a certain point via gdb results in the error

Program received signal SIGTRAP, Trace/breakpoint trap.

That point is where the autorelease pool which was created for the invocation of getArtist gets released. All other properties are fine, though... so - after all the error lies in the codepart I posted in my first edit?

A: 

Find out where you populate your array. Most likely, you have over-released one of the strings that you have inserted in your array. When the encoder object tries to access the over-released object, you get the error.

dreamlax
+1  A: 

Either your GetDetails class is borked or whoever is calling it is borked. Specifically, see this part of the allocation trace:

+[GetDetails getArtist:summary:theURL:]
-[CXMLNode stringValue]

If implemented correctly, CXMLNode's stringValue method is returning an autoreleased string. Something needs to invoke -retain on it (directly or via a property setter).

Or, possibly, the getArtist:summary:theURL: method is designed to return a retained string? If so, then it should return the result of stringValue before returning it.

Without seeing more code, it is impossible to say more. If I were the wagering type, I suspect getArtist:summary:theURL: is returning the artist and summary by reference? If so, that is a mighty goofy design -- atypical, even -- but I'd bet the caller is assuming that the artist and/or summary are retained when they are not? .... or there is an extra -autorelease call somewhere?

bbum
I edited my original post to add some more code. getArtist is supposed to return an Artist object only, summary will eventually be saved as a property of the artist object.
ff10