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

lvi*_*ani 0 objective-c touchxml ios

我正在努力学习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
Run Code Online (Sandbox Code Playgroud)

(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
Run Code Online (Sandbox Code Playgroud)

后来在另一堂课中我做了:

- (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);
}
Run Code Online (Sandbox Code Playgroud)

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

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

bbu*_*bum 5

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

请注意,"未被分配的指针"意味着某人调用free()(或dealloc有效地)指向一块未首先分配的内存的指针.它通常会为您提供一个断点,您可以设置该断点,然后回溯确切的位置.

一些评论:

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

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

(3)你应该使用ARC.