为什么此代码会在仪器上泄漏?

发布于 2024-10-31 09:55:58 字数 3005 浏览 6 评论 0原文

我正在仪器上进行一些内存分析,我觉得我的代码似乎正在执行正确的内存管理。然而,仪器确信我正在泄漏,但我不知道如何使泄漏消失。

在我的 Event.h 中我有。


@property (nonatomic, copy) NSString *organizer;
@property (nonatomic, copy) NSString *type;
@property (nonatomic, retain) NSDate *startTime;
@property (nonatomic, retain) NSDate *endTime;
@property (nonatomic, copy) NSString *coverCharge;
@property (nonatomic, copy) NSString *ageLimit;
@property (nonatomic, copy) NSString *dressCode;
@property (nonatomic, copy) NSString *venueName;
@property BOOL attendingFlag;

它们都在 dealloc 中发布


- (void) dealloc {
    [type release];
    [organizer release];
    [startTime release];
    [endTime release];
    [coverCharge release];
    [ageLimit release];
    [dressCode release];
    [venueName release];
    [super dealloc];
}   

,在我的工厂类中,


-(Event*) getEvent:rs {
    Event *event = [[Event alloc] init];
    event.objId = [NSNumber numberWithInt:[rs intForColumn:DATABASE_EVENT_ID_FIELD]];
    event.name= [rs stringForColumn:DATABASE_EVENT_NAME_FIELD];
    event.organizer = [rs stringForColumn:DATABASE_EVENT_ORGANIZER_FIELD];
    event.type = [rs stringForColumn:DATABASE_EVENT_TYPE_FIELD];
    event.desc= [rs stringForColumn:DATABASE_EVENT_DESCRIPTION_FIELD];
    event.venueName = [rs stringForColumn:DATABASE_EVENT_VENUE_NAME_FIELD];
    event.coverCharge= [rs stringForColumn:DATABASE_EVENT_COVER_CHARGE_FIELD];
    event.dressCode = [rs stringForColumn:DATABASE_EVENT_DRESS_CODE_FIELD];
    event.ageLimit = [rs stringForColumn:DATABASE_EVENT_AGE_LIMIT_FIELD];
    event.region = [[[Region alloc] initWithIdAndName:[NSNumber numberWithInt:[rs intForColumn:DATABASE_EVENT_REGION_ID_FIELD]] name:[rs stringForColumn:DATABASE_EVENT_REGION_NAME_FIELD]] autorelease];
    event.community = [[[Community alloc] initWithIdAndName:[NSNumber numberWithInt:[rs intForColumn:DATABASE_EVENT_COMMUNITY_ID_FIELD]] name:[rs stringForColumn:DATABASE_EVENT_COMMUNITY_NAME_FIELD]] autorelease];
    event.address = [rs stringForColumn:DATABASE_EVENT_ADDRESS_FIELD];
    event.address2 = [rs stringForColumn:DATABASE_EVENT_ADDRESS2_FIELD];
    event.city = [rs stringForColumn:DATABASE_EVENT_CITY_FIELD];
    event.state = [rs stringForColumn:DATABASE_EVENT_STATE_FIELD];
    event.zip = [rs stringForColumn:DATABASE_EVENT_ZIP_FIELD];
    event.country = [rs stringForColumn:DATABASE_EVENT_COUNTRY_FIELD];
    event.phone = [rs stringForColumn:DATABASE_EVENT_PHONE_FIELD];
    event.webpage = [rs stringForColumn:DATABASE_EVENT_WEBPAGE_FIELD];

    return [event autorelease];
}

您可能会注意到,我在事件上设置的属性比上面提到的要多,那是因为我有事件扩展了另一个更通用的实体。我什至没有发布该代码的原因是因为根据仪器,我什至泄漏了 Event 类本身的设置器。

Instruments 抱怨事件分配上存在泄漏,并且 getEvent 选择器中的每一行都存在泄漏。 rs 是来自我在整个应用程序中使用的库(FMDB)的结果集对象,这似乎是检测到这些泄漏的唯一实体,所以我很确定这不是问题。实际上,我最近在另一个项目中使用了同一个库,并且没有由此引起的泄漏,因此我已将其作为泄漏源消除。

(a) 当我返回事件对象时,我显然会自动释放它。

(b) 我的所有设置器都获得自动释放的对象,因此我只按照目标 c 的内存管理文档的建议增加保留计数。

知道为什么 alloc 行和它后面的几乎每一行都可能泄漏吗?

I'm doing some memory profiling on instruments and I feel like I have code that seems to be doing proper memory management. However, instruments is convinced that I'm leaking and I can't figure out how to make the leak go away.

In my Event.h I have.


@property (nonatomic, copy) NSString *organizer;
@property (nonatomic, copy) NSString *type;
@property (nonatomic, retain) NSDate *startTime;
@property (nonatomic, retain) NSDate *endTime;
@property (nonatomic, copy) NSString *coverCharge;
@property (nonatomic, copy) NSString *ageLimit;
@property (nonatomic, copy) NSString *dressCode;
@property (nonatomic, copy) NSString *venueName;
@property BOOL attendingFlag;

They're all released in dealloc


- (void) dealloc {
    [type release];
    [organizer release];
    [startTime release];
    [endTime release];
    [coverCharge release];
    [ageLimit release];
    [dressCode release];
    [venueName release];
    [super dealloc];
}   

And in my factory class, I have


-(Event*) getEvent:rs {
    Event *event = [[Event alloc] init];
    event.objId = [NSNumber numberWithInt:[rs intForColumn:DATABASE_EVENT_ID_FIELD]];
    event.name= [rs stringForColumn:DATABASE_EVENT_NAME_FIELD];
    event.organizer = [rs stringForColumn:DATABASE_EVENT_ORGANIZER_FIELD];
    event.type = [rs stringForColumn:DATABASE_EVENT_TYPE_FIELD];
    event.desc= [rs stringForColumn:DATABASE_EVENT_DESCRIPTION_FIELD];
    event.venueName = [rs stringForColumn:DATABASE_EVENT_VENUE_NAME_FIELD];
    event.coverCharge= [rs stringForColumn:DATABASE_EVENT_COVER_CHARGE_FIELD];
    event.dressCode = [rs stringForColumn:DATABASE_EVENT_DRESS_CODE_FIELD];
    event.ageLimit = [rs stringForColumn:DATABASE_EVENT_AGE_LIMIT_FIELD];
    event.region = [[[Region alloc] initWithIdAndName:[NSNumber numberWithInt:[rs intForColumn:DATABASE_EVENT_REGION_ID_FIELD]] name:[rs stringForColumn:DATABASE_EVENT_REGION_NAME_FIELD]] autorelease];
    event.community = [[[Community alloc] initWithIdAndName:[NSNumber numberWithInt:[rs intForColumn:DATABASE_EVENT_COMMUNITY_ID_FIELD]] name:[rs stringForColumn:DATABASE_EVENT_COMMUNITY_NAME_FIELD]] autorelease];
    event.address = [rs stringForColumn:DATABASE_EVENT_ADDRESS_FIELD];
    event.address2 = [rs stringForColumn:DATABASE_EVENT_ADDRESS2_FIELD];
    event.city = [rs stringForColumn:DATABASE_EVENT_CITY_FIELD];
    event.state = [rs stringForColumn:DATABASE_EVENT_STATE_FIELD];
    event.zip = [rs stringForColumn:DATABASE_EVENT_ZIP_FIELD];
    event.country = [rs stringForColumn:DATABASE_EVENT_COUNTRY_FIELD];
    event.phone = [rs stringForColumn:DATABASE_EVENT_PHONE_FIELD];
    event.webpage = [rs stringForColumn:DATABASE_EVENT_WEBPAGE_FIELD];

    return [event autorelease];
}

You may notice that I'm setting more attributes on the event than I have mentioned above and that's because I have Event extending another Entity which is more generic. The reason I didn't even post that code is because according to instruments, I'm leaking on even the setters for the Event class itself.

Instruments complains that there is a leak on the Event alloc and another one on every line in the getEvent selector. The rs is a resultset object from a library (FMDB) that I'm using all over the app and this seems to be the only entity where these leaks are detected so I'm pretty sure that's not the issue. I've actually used this same library for another project recently, and there were no leaks caused by it so I've eliminated it as the source of the leak.

(a) I'm clearly autoreleasing the event object when I return it.

(b) All my setters are getting autoreleased objects so I'm only increasing the retain count as recommended by the memory management docs for objective c.

Any idea why the alloc line and almost every line following it may be leaking?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

寂寞美少年 2024-11-07 09:55:58

答案是其他地方的代码正在保留您的 Event 对象。泄漏只能显示已泄漏的内存是在哪里创建的,泄漏不能显示应该编写的代码以在创建后正确释放对象!

其他行都被标记为泄漏,因为 Event 对象正在泄漏。

要做的事情是除了泄漏之外还添加分配工具,并确保将其设置为“记录引用计数”(时间图上分配栏中的小 (i))。然后启动您的应用程序,观察泄漏情况。然后选择分配工具,选择“已创建且仍然存在”,然后查找仍然存在的事件对象。

然后单击地址旁边的箭头,您将获得该对象的每个保留和释放的列表。您通常可以从中找出是什么保留了本来应该稍后释放它但没有释放的对象。

The answer is that code elsewhere is retaining your Event object. Leaks can only show you where memory that has been leaked was created, Leaks cannot show you the code that should have been written to correctly release the object after creation!

The other lines are all marked as leaks because the Event object is leaking.

The thing to do is to add the Allocations instrument in addition to Leaks, and make sure it's set to "record reference counts" (little (i) in the Allocations bar on the time graph). Then start your app, observe the leak. Then select the Allocations tool, select "created and still living", and look up Event objects still around.

Then click on the arrow next to the address, and you'll get a list of every retain and release for that object. You can usually figure out from that what retained the object that should have also released it later but did not.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文