0

I'm trying to learn objective-c (I'm very new to that) and I have issues with memory management...

I'm developing an iPad app that uses TouchXML.

I've created my class that extends CXMLDocument and does some initialisation by reading some contents and saving into properties.

Here is my code (SimpleManifest.h):

@interface SimpleManifest : CXMLDocument {
    CXMLNode *_defaultOrganization;
    NSString *_title;

    NSDictionary *dictionary;
}

@property (readonly) CXMLNode *defaultOrganization;
@property (readonly) NSString* title;

- (id) initWithPath:(NSString *)path options:(NSUInteger)options error:(NSError **)error;

@end

(SimpleManifest.m):

#import "SimpleManifest.h"
#import "CXMLNode_XPathExtensions.h"

@implementation SimpleManifest

- (id) initWithPath:(NSString *)path options:(NSUInteger)options error:(NSError **)error
{
    /*
    NSURL *theURL = [[[NSURL alloc] initFileURLWithPath:path] autorelease];
    self = [self initWithContentsOfURL:theURL options:options error:error];
    */

    NSData *data   = [NSData dataWithContentsOfFile:path];
    NSString *s = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];

    self = [self initWithXMLString:s options:options error:error];

    if (self==nil) return nil;

    // load main props

    dictionary = [NSDictionary dictionaryWithObjectsAndKeys:
                  @"http://www.imsglobal.org/xsd/imscp_v1p1", @"imscp",
                  @"http://ltsc.ieee.org/xsd/LOM", @"lom", nil];


    // defualt organization
    @try {


        CXMLNode *orgsElem = [[[self childAtIndex:0] nodesForXPath:@"//imscp:organizations" namespaceMappings:dictionary error:nil] objectAtIndex:0];
        NSString *xpath = [NSString stringWithFormat:@"//imscp:organization[@identifier='%@']", [[orgsElem attributeForName:@"default"] stringValue]];

        _defaultOrganization = [[[self childAtIndex:0] nodesForXPath:xpath namespaceMappings:dictionary error:nil] objectAtIndex:0];


        /*
        NSArray *nodes = [[self childAtIndex:0] nodesForXPath:@"//imscp:organizations" namespaceMappings:dictionary error:nil];
        NSString *xpath = [NSString stringWithFormat:@"//imscp:organization[@identifier='%@']", [[[nodes objectAtIndex:0] attributeForName:@"default"] stringValue]];
        _defaultOrganization = [[[self childAtIndex:0] nodesForXPath:xpath namespaceMappings:dictionary error:nil] objectAtIndex:0];
        */

        CXMLNode *titleElem = [[[self childAtIndex:0]
                                  nodesForXPath:@"//lom:general/lom:title/lom:string"
                                  namespaceMappings:dictionary
                                  error:nil] objectAtIndex:0];

        _title = [[titleElem stringValue] copy];

    } @catch (NSException * e){
        self = nil;
        return nil;
    }


    return self;
}
@end

Later on in another class I do:

- (BOOL) isValidSCORMLesson:(NSString*) path {
    NSString *manifPath = [path stringByAppendingPathComponent:@"imsmanifest.xml"];
    if (![[NSFileManager defaultManager] fileExistsAtPath: manifPath isDirectory: NO])
        return NO;

    SimpleManifest *manifest = [[[SimpleManifest alloc] initWithPath:manifPath options:0 error:nil] autorelease];
    NSLog(@"%@", manifest.defaultOrganization);
    NSLog(@"%@", manifest.title);

    return (manifest!=nil);
}

It gives me tons of "pointer being freed was not allocated" errors... The thing changes if I comment out the NSLog calls above or just log the manifest.title property. Project is not using ARC, so I'm sure I'm doing something wrong with memory management.

Can someone please help me understand where I'm doing wrong? Thanks!

Kara
  • 6,115
  • 16
  • 50
  • 57
lviggiani
  • 5,824
  • 12
  • 56
  • 89

1 Answers1

5

There isn't anything obviously wrong with that code that would cause malloc errors. Best guess is that there is a bug in the CXMLDocument class/library or some mistake in the way you are using it.

Note that a "pointer being freed was not allocated" means that someone called free() (or dealloc, effectively) on a pointer to a piece of memory that was not allocated in the first place. It usually gives you a breakpoint you can set that will then give you a backtrace of exactly where it happened.

Some comments:

(1) Do not @try/@catch in that fashion. Just don't catch at all. The pattern you are using will hide any errors. Exceptions are not meant to be recoverable in iOS/Cocoa.

(2) You can create an NSString instance directly from a file; no need to load via NSData first.

(3) You should use ARC.

bbum
  • 162,346
  • 23
  • 271
  • 359
  • @bbum : and what about using ivars and properties, for example he is using iVars (NSString *_title;...). Should we prefere using properties or it's the same thing. Thanks – samir Jun 03 '13 at 15:48
  • Thanks for the answers... in the mean time, I discovered that by changing "@property (readonly) NSString* title;" to "@property (readonly) NSString *title;" (just moving the star next to title) stopped giving the error. Then after reading some other nodes, I got the error back again and I discovered that cleaning the project and building again stopped the error message once more... I'm confused. – lviggiani Jun 03 '13 at 16:02
  • About ARC: I've disabled it because the documentation of TouchXML says that it is not supported... also Im using "[backingWebView _setWebGLEnabled:YES];" later in my code that, with ARC disabled just gives me a warning, whereas with ARC enabled gives me an "instance method not found" and does not compile. Any idea? – lviggiani Jun 03 '13 at 16:05
  • You can mix ARC and non-ARC just fine. As long as TouchXML follows proper memory management conventions, your code can be ARC while TouchXML remains MRR. If TouchXML doesn't follow said conventions, probably best not to use it anyway. ARC's errors-that-are-only-warnings-under-MRR are because they really should be errors. Sounds like you didn't #import the file with the declaration. – bbum Jun 03 '13 at 18:20
  • In the end I found out the problem: I was subclassing CXMLDocuement and this was causing memory management issues. – lviggiani Jun 07 '13 at 18:48
  • Subclassing doesn't cause memory management issues directly; sounds like you fixed a symptom, but may still have a lurking problem! – bbum Jun 07 '13 at 19:35