Objective c ARC和重复使用指针会耗尽内存
在ARC实现之前,我一直在考虑保留和发布,我倾向于尝试重用指针,以避免一直需要重新声明它们 但使用ARC时,会产生泄漏。我的猜测是,它只是释放分配给“tmp”指针的最后一个对象,我假设当我给指针一个新对象时,旧对象会自动释放。在autoreleasepool中封装函数似乎可以完成这项工作,但这真的是理想的解决方案还是我的编码风格错了 这是一个有罪的函数,在我运行了几百次之后,它似乎吞噬了我所有的内存:Objective c ARC和重复使用指针会耗尽内存,objective-c,ios,automatic-ref-counting,Objective C,Ios,Automatic Ref Counting,在ARC实现之前,我一直在考虑保留和发布,我倾向于尝试重用指针,以避免一直需要重新声明它们 但使用ARC时,会产生泄漏。我的猜测是,它只是释放分配给“tmp”指针的最后一个对象,我假设当我给指针一个新对象时,旧对象会自动释放。在autoreleasepool中封装函数似乎可以完成这项工作,但这真的是理想的解决方案还是我的编码风格错了 这是一个有罪的函数,在我运行了几百次之后,它似乎吞噬了我所有的内存: - (void) saveJDictEntry:(JDictEntry *)entry {
- (void) saveJDictEntry:(JDictEntry *)entry {
const char * query;
char * errMsg;
NSString *queryString;
sqlite3_stmt * statement;
[self connect];
// Insert the word..
queryString = [NSString stringWithFormat:@"INSERT INTO words (seq) VALUES (%i)", entry.number];
query = [queryString UTF8String];
if (sqlite3_exec(database, query, NULL, NULL, &errMsg) != SQLITE_OK) {
NSLog(@"Statement failed %@ %@", errMsg, queryString);
}
// Get the last id we inserted..
NSUInteger lastId = 0;
queryString = @"SELECT last_insert_rowid()";
query = [queryString UTF8String];
sqlite3_prepare_v2(database, query, -1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_ROW) {
lastId = sqlite3_column_int(statement, 0);
} else {
NSLog(@"Failed to fetch last Id after saving");
}
sqlite3_finalize(statement);
entry.databaseId = lastId;
entry.saved = true;
// Kana...
queryString = [NSString stringWithFormat:@"INSERT INTO words_kana (word_id, kana) VALUES (%i, '%@')", entry.databaseId, entry.kana ];
query = [queryString UTF8String];
if (sqlite3_exec(database, query, NULL, NULL, &errMsg) != SQLITE_OK) {
NSLog(@"Statement failed %@ %@", errMsg, queryString);
}
// Kanji ...
for(NSString * _kanji in entry.kanji) {
queryString = [NSString stringWithFormat:@"INSERT INTO words_kanji (word_id, kanji) VALUES (%i, '%@')", entry.databaseId, _kanji];
query = [queryString UTF8String];
if (sqlite3_exec(database, query, NULL, NULL, &errMsg) != SQLITE_OK) {
NSLog(@"Statement failed %@ %@", errMsg, queryString);
}
}
// Pos..
for(NSString * _pos in entry.pos) {
queryString = [NSString stringWithFormat:@"INSERT INTO words_pos (word_id, pos) VALUES (%i, '%@')", entry.databaseId, _pos];
query = [queryString UTF8String];
if (sqlite3_exec(database, query, NULL, NULL, &errMsg) != SQLITE_OK) {
NSLog(@"Statement failed %@ %@", errMsg, queryString);
}
}
// Gloss
for(NSString * _gloss in entry.gloss) {
NSString * glossField = [_gloss stringByReplacingOccurrencesOfString:@"'" withString:@"''"];
queryString = [NSString stringWithFormat:@"INSERT INTO words_gloss (word_id, gloss) VALUES (%i, '%@')", entry.databaseId, glossField];
query = [queryString UTF8String];
if (sqlite3_exec(database, query, NULL, NULL, &errMsg) != SQLITE_OK) {
NSLog(@"Statement failed %@ %@", errMsg, queryString);
}
}
}
我试过你举的例子。没有泄漏,绝对没有:既不在iOS5应用程序上,也不在桌面应用程序上。还检查了仪器。(Xcode 4.2.1,Build 4D502,使用LLVM 3.0编译)我尝试了您给出的示例。没有泄漏,绝对没有:既不在iOS5应用程序上,也不在桌面应用程序上。还检查了仪器。(Xcode 4.2.1,Build 4D502,使用LLVM 3.0编译)旧的内存管理概念仍然适用于全局释放池中的自动释放实例在完成当前运行循环之前不会被释放,无论有无ARC 如果您正在编写非琐碎的迭代,例如数千次迭代,那么使用自动释放池包装它是一种方法。你可以用
@autoreleasepool {
// your code here
}
为了简化使用。使用自动释放池并没有任何错误或不理想的地方,因为它是出于某种原因而存在的。顾名思义,ARC只进行自动引用计数。管理内存使用的任务仍然属于我们。旧的内存管理概念仍然适用于全局释放池中的自动释放实例在完成当前运行循环之前不会被释放,无论有无ARC 如果您正在编写非琐碎的迭代,例如数千次迭代,那么使用自动释放池包装它是一种方法。你可以用
@autoreleasepool {
// your code here
}
为了简化使用。使用自动释放池并没有任何错误或不理想的地方,因为它是出于某种原因而存在的。顾名思义,ARC只进行自动引用计数。管理内存使用的任务仍然属于我们。这不是真正的代码,是吗?你在分配静力学,没有什么可以泄露的。如果你想得到真实的答案,请发布真实的代码。静态分析器是否注意到这是一个漏洞,或者是仪器的漏洞?谢谢,我已经发布了一些真实的代码-但除非我很厚(很可能),否则这是同一个概念。我收到内存警告,然后强制退出,除非我将其包装在自动释放池中。这不是真正的代码,是吗?你在分配静力学,没有什么可以泄露的。如果你想得到真实的答案,请发布真实的代码。静态分析器是否注意到这是一个漏洞,或者是仪器的漏洞?谢谢,我已经发布了一些真实的代码-但除非我很厚(很可能),否则这是同一个概念。我收到内存警告,然后强制退出,除非我将其包装在自动释放池中。谢谢,我不知道它会一直保留到循环结束。该函数在另一个循环中调用,该循环位于一个大导入器循环中。。因此,我猜它之所以会保留它们,是因为这个原因。@RoyalFool-除了使用自动释放池包装外,您还可以尝试使用
-stringWithFormat:
等方法替换方便的构造函数,如-initWithFormat:
,以避免从代码的这些部分获取自动释放的实例。这将减少自动释放对象的聚合。谢谢,我不知道它会一直保存到完成循环为止。该函数在另一个循环中调用,该循环位于一个大导入器循环中。。因此,我猜它之所以会保留它们,是因为这个原因。@RoyalFool-除了使用自动释放池包装外,您还可以尝试使用-stringWithFormat:
等方法替换方便的构造函数,如-initWithFormat:
,以避免从代码的这些部分获取自动释放的实例。这将减少自动释放对象的聚合。