Objective c,内存泄漏,从 sqlite 读取并将值分配给 NSDictionary 和 NSAarray
我在 ListController 文件中有一个商店列表。 我建立了一个 sqlite 数据库,其中存储了 60 个商店。 在列表的顶部我有一个搜索栏。
我创建了一个名为 DataController 的类,负责加载和存储数据库数据。
@interface DataController : NSObject {
sqlite3 *database;
NSArray *shops;
NSDictionary* dictionaryOfShops;
}
@property (nonatomic, retain) NSDictionary *dictionaryOfShops;
@property (nonatomic, retain) NSArray* shops;
-(void)initializeShops;
initializeShops 方法从数据库加载数据,并以这种方式将结果存储到 2 个道具中:
-(void)initializeShops{
[dictionaryOfShops release];
[shops release];
NSMutableDictionary *dictionary = [[[NSMutableDictionary alloc] init] autorelease];
if (sqlite3_open(....))
NSString *query = ....
if (sqlite3_prepare_v2(database, [query UTF8String],-1, &statement, nil) == SQLITE_OK)
{
while (sqlite3_step(statement) == SQLITE_ROW) {
int rId = sqlite3_column_int(statement, 0);
char *rName = (char *)sqlite3_column_text(statement, 1);
Shop* s = [[Shop alloc] init];
s.ID = rId;
if(sName != nil) s.Name = [NSString stringWithUTF8String:rName];
NSString *shopID = [[NSString alloc] initWithFormat:@"%d",s.ID];
[dictionary setObject:s forKey:shopID];
[shopID release];
[s release];
}
sqlite3_finalize(statement);
}
[query release];
dictionaryOfShops = [[NSDictionary alloc] initWithDictionary:dictionary];
shops = [[NSArray alloc] initWithArray:[dictionary allValues]];
dictionary = nil;
[dictionary release];
//Sorting
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"Name" ascending:YES];
NSArray *sortedList =[self.shops sortedArrayUsingDescriptors:[NSArray arrayWithObject:sort]];
self.shops = sortedList;
[sort release];
}
问题是,当用户在搜索中输入一些文本时 吧,我更改了查询的值(添加 LIKE....),然后再次调用initializeShops 方法。这第二次使得 如此多的泄漏(与 Shop 类属性相关)和 还泄漏了 NSDictionary 和 NSArray。
在向您发布此内容之前,我尝试了不同的解决方案,但是 至少我第一次打电话时不会泄露任何信息 初始化商店。
我接受任何建议,因为我真的被困住了 在它上面。
更多:
真正奇怪的是我的 var 字典和 2 个道具商店和dictionaryOfShops 的内存管理。使用此代码
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
//add data to dictionary
dictionaryOfShops = [[NSDictionary alloc] initWithDictionary:dictionary];
shops = [[NSArray alloc] initWithArray:[dictionary allValues]];
[dictionary release]
考虑到dictionaryOfShops和商店是合成的两个属性(非原子,保留),如何在不泄漏的情况下更改它们的值?
我第一次通过这个方法时没有任何泄漏,从第二次开始它开始泄漏这么多对象(集合的内容)。
I have a list of shops in a ListController file.
I've setted up a sqlite db, in which i've stored 60 shops.
On the top of the list i have a search bar.
I've made a class called DataController, that is responsible to load and store db datas.
@interface DataController : NSObject {
sqlite3 *database;
NSArray *shops;
NSDictionary* dictionaryOfShops;
}
@property (nonatomic, retain) NSDictionary *dictionaryOfShops;
@property (nonatomic, retain) NSArray* shops;
-(void)initializeShops;
initializeShops method loads data from the db, and stores results into the 2 props in this way:
-(void)initializeShops{
[dictionaryOfShops release];
[shops release];
NSMutableDictionary *dictionary = [[[NSMutableDictionary alloc] init] autorelease];
if (sqlite3_open(....))
NSString *query = ....
if (sqlite3_prepare_v2(database, [query UTF8String],-1, &statement, nil) == SQLITE_OK)
{
while (sqlite3_step(statement) == SQLITE_ROW) {
int rId = sqlite3_column_int(statement, 0);
char *rName = (char *)sqlite3_column_text(statement, 1);
Shop* s = [[Shop alloc] init];
s.ID = rId;
if(sName != nil) s.Name = [NSString stringWithUTF8String:rName];
NSString *shopID = [[NSString alloc] initWithFormat:@"%d",s.ID];
[dictionary setObject:s forKey:shopID];
[shopID release];
[s release];
}
sqlite3_finalize(statement);
}
[query release];
dictionaryOfShops = [[NSDictionary alloc] initWithDictionary:dictionary];
shops = [[NSArray alloc] initWithArray:[dictionary allValues]];
dictionary = nil;
[dictionary release];
//Sorting
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"Name" ascending:YES];
NSArray *sortedList =[self.shops sortedArrayUsingDescriptors:[NSArray arrayWithObject:sort]];
self.shops = sortedList;
[sort release];
}
The problem is that when user enters some text into the search
bar, I change the value of the query (adding LIKE....) and then call the initializeShops method again. This second time makes
so many leaks, (related to the Shop class properties) and
leaks also a NSDictionary and a NSArray.
Before posting this to you I've tried different solutions, but
at least this doesn't leaks anything the first time I call
initilizeShops.
I accept any suggestion, since I'm really stuck
on it.
MORE:
The really strange thing is memory management of my var dictionary and the 2 props shops and dictionaryOfShops. With this code
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
//add data to dictionary
dictionaryOfShops = [[NSDictionary alloc] initWithDictionary:dictionary];
shops = [[NSArray alloc] initWithArray:[dictionary allValues]];
[dictionary release]
Considering that dictionaryOfShops and shops are two properties (nonatomic,retain) synthesized, how can I change value to them without leaks?
The very first time I pass through this method nothing gets leaked, from the second time it starts to leak so many objects (the contents of the collections).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
第一个问题是为什么不直接使用 Core Data?它很可能会更快,需要更少的代码,并且随着时间的推移会更容易维护。直言不讳; SQLite 看似困难。上手容易,做对却异常困难。
无论如何,
dictionary
的内存管理是错误的。它只是没有崩溃,因为您按照 kennyTM 建议交换了 nil 赋值和释放的顺序。我建议不要创建自动发布的字典。否则,乍一看所编写的代码似乎非常完美。所以:
你能提供更多代码吗?
任何有趣的记忆
其他地方发生了什么?
您是否使用了线程(或者
NSOperationQueue)?
你有没有遇到过泄密事件?
仪器并检索到
分配的回溯
特定对象被泄漏?
The first question is Why not just use Core Data? It is very likely going to be faster, will require less code, and will be significantly easier to maintain over time. To be blunt; SQLite is deceptively hard. Easy to get started, exceptionally difficult to get right.
In any case, the memory management of
dictionary
is wrong. It only isn't crashing because you swapped the order of the nil assignment and release as kennyTM suggested. I would suggest not creating an autoreleased dictionary.Otherwise, the code as written seems pretty leakless at first glance. So:
Can you provide some more code?
Anything interesting memory wise
going on elsewhere?
Are you using threading at all (or
NSOperationQueue)?
Have you run under the Leaks
instrument and retrieved the
backtraces of allocation of the
specific objects being leaked?
请交换这两个语句。在这种形式中,它意味着
[nil release]
,这是一个无操作。Please swap these 2 statements. In this form it means
[nil release]
which is a no-op.好的,我找到了错误。
在我的 Shop 类中,我意识到我没有实现该方法
,因此当我释放旧字典(以准备新作业)时,其中的所有字段都没有被释放。
Ok, I've found the error.
In my class Shop, i realize i didn't implement the method
So when I release the old dictionary (to prepare for a new assignment), all the fields inside of it didn't get released.