2010-04-22 46 views
0

我创建了一个调用Web服务的图形应用程序。用户可以放大图形的移动范围,程序偶尔会决定调用Web服务以获取更多数据。这是通过以下过程实现的:Objective-C内存管理问题

该图具有呈现循环,该循环不断呈现图形,以及将Web服务调用信息添加到堆栈的一些决策逻辑。

单独的线程从堆栈中获取最新的Web服务调用信息,并使用它来进行Web服务调用。堆栈中的其他对象被分类。

这样做的想法是将Web服务调用的数量减少到仅适用的那些,并且一次只有一个。

权,与长故事的方式进行(对此我表示歉意),这里是我的内存管理问题:

有图有持续性(和适当锁定)的NSDate *当前显示的对象开始&图表的结束时间。这些传递给我的Web服务请求对象的初始化程序。 Web服务调用对象然后保留日期。

Web服务调用完成后(或者如果它们已过期,则为binned),它们释放NSDate *。

该图本身在“触摸已结束”事件中释放并重新分配新的NSDates *。

如果在调用removeAllObjects时堆栈上只有一个Web服务调用对象,则在Web服务调用对象的释放方法尝试释放日期对象时发生EXC_BAD_ACCESS(即使它们看起来存在且处于作用域中在调试器中)。

但是,如果我从析构函数注释掉释放消息,则释放堆栈上的一个对象时不会发生内存泄漏,但如果堆栈中有多个对象,则会发生内存泄漏。

我完全不知道怎么回事。它没有什么区别我用于Web服务调用对象的存储语义,因为它们是在初始化程序中分配的,然后才被读取(所以为了正确性而设置为只读)。

如果我在初始化程序中保留或复制日期(尽管其他任何明显超出范围或在别处释放并导致崩溃),似乎也没有什么区别。

对不起,这个解释很长,我希望它已经足够清晰,但我不是在赌博,或者我害怕。非常感谢任何能提供帮助的人,甚至提出我可能错过的任何事情?

要明确希望事情了一下,这里是一些伪(ISH)代码...东西(不包括锁和initialisers):

NSMutableArray* requests; 
NSDate* start, end; 

-(void)webServiceThread 
{ 
    if([requests count] > 1) 
    { 
     [self doRequestWithParams:[requests lastObject]]; 
     [requests removeAllObjects]; 
    } 
} 

-(void)render 
{ 
    if(conditions for another web service call are met) 
    { 
     WebServiceRequest* new = [[WebServiceRequest alloc] initWithDates:start :end]; 
     [requests addObject:new]; 
     [new release]; 
    } 

    [self doRendering]; 
} 

-(void)touchesEnded 
{ 
    [start release]; 
    [end release]; 
    start = [[NSDate dateSinceTimeInterval:chartLeft] retain]; //Ficticious NSDate Method names for example. 
    end = [[NSDate dateSinceTimeInterval:chartRight] retain]; 
} 

然后在Web服务调用对象:

NSDate* startDate; 
NSDate* endDate; 

-(void)initWithDates:start :end 
{ 
    startDate = [start retain]; 
    endDate = [end retain]; 
} 

-(void)dealloc 
{ 
    [super dealloc]; 

    //The following two lines cause EXC_BAD_ACCESS if this is the only object on the request stack. If they are commented, however, memory is leaked if this is not the only object on the request stack. 
    [startDate release]; 
    [endDate release]; 
} 
+0

这听起来像是有一个释放到很多。从你的解释来看,这听起来像是这个额外释放发生的地方并不明显。我想在某种程度上autorelease必须偷偷溜进去,你错过了。如果您可以发布相关代码 - 所有作业,保留和发布日期,这将有所帮助。 – 2010-04-22 13:49:57

+0

作为一个小提示,尽管不需要,在'dealloc'中最后调用'[super dealloc]'最后通常更安全。 http://stackoverflow.com/questions/909856/why-do-i-have-to-call-super-dealloc-last-and-not-first – 2010-04-22 13:58:44

+0

感谢您的回复,已添加伪代码(实际代码是大量的更长;也可能是问题的一部分)。自动释放的想法没有发生在我身上,但是在适用的情况下,所有东西都有一个存储方法(目前保留)。 – Tobster 2010-04-22 13:58:58

回答

0

把[super dealloc]修好的问题;在destructor的结尾。感谢Toon Van Acker。

出于兴趣;可以任意说,如果相同的原则适用于其他方法,如[超级初始化]?

+0

您必须最后调用[super dealloc]。一旦它被调用,你就不能保证你的任何ivars都有效了,因为[super dealloc]最终调用了[NSObject dealloc],它释放了内存并使其可以重用。 [super init]必须在你自己的任何初始化代码之前完成,并且它的返回值赋给self。 – JeremyP 2010-04-22 14:59:47