Objective C内存管理 - “未释放指针被释放”错误

时间:2013-06-03 15:27:27

标签: ios objective-c touchxml

我正在尝试学习objective-c(我对此非常新)并且我在内存管理方面存在问题......

我正在开发一款使用TouchXML的iPad应用程序。

我创建了扩展CXMLDocument的类,并通过读取一些内容并保存到属性中进行初始化。

这是我的代码(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

稍后在另一节课中我做了:

- (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);
}

它给了我很多“指针被释放没有分配”的错误...... 如果我注释掉上面的NSLog调用或者只记录manifest.title属性,那么事情就会改变。 Project没有使用ARC,所以我确定我在内存管理方面做错了。

有人可以帮我理解我做错了吗?谢谢!

1 个答案:

答案 0 :(得分:5)

该代码没有任何明显错误会导致malloc错误。最好的猜测是,CXMLDocument类/库中存在错误,或者您使用它时出现了一些错误。

请注意,“未分配的指针”表示有人在指向未首先分配的内存的指针上有效地调用free()(或dealloc)。它通常会为您提供一个断点,您可以设置断点,然后回溯确切的位置。

一些意见:

(1)不要以这种方式@ try / @ catch。只是不要抓住。您使用的模式将隐藏任何错误。在iOS / Cocoa中,异常并不是可以恢复的。

(2)您可以直接从文件创建NSString实例;无需先通过NSData加载。

(3)你应该使用ARC。