2011-04-07 108 views
0

嗨,所有我有一个类与我的应用程序中的sqlite数据库一起工作。在这里你可以看到我写的一个函数。该函数必须获得列值等于给定值的项目数。我应该使用AutoreleasePool吗?

+ (int) GetCountOfItems: (NSString*) byColumn { 
     // Autorelease Pool. 
     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc]init]; 
     // Create Sqlite query string. 
     NSString* sqliteQuery = [NSString stringWithFormat:@"SELECT COUNT(*) FROM [Articles] WHERE %@ = 1", byColumn]; 
     NSLog(@"GetCountOfItems query string is: %@", sqliteQuery); 
     // Create statement. 
     sqlite3_stmt* stmt; 
     int articleCount = 0; 

     if(sqlite3_prepare_v2(database, [sqliteQuery UTF8String], -1, &stmt, NULL) == SQLITE_OK) { 
      if(sqlite3_step(stmt) == SQLITE_ROW) 
       articleCount = sqlite3_column_int(stmt, 0); 
     } 
     else NSLog(@"Failed from GetCountOfItems. Error is: %c", sqlite3_errmsg(database)); 

     // Finalize. 
     sqlite3_finalize(stmt); 

     // Release Pool. 
     [pool release]; 

     return articleCount; 
    } 

我想知道,如果这个功能是正确的,例如我应该使用NSAutoreleasePool *池= [[NSAutoreleasePool的alloc]初始化] ????它如何可以帮助我的记忆?

+1

有足够的问号吗? – mxcl 2011-04-07 12:07:07

回答

2

基于以下描述(在Memory Management Programming Guide):

中的应用工具包自动创建在事件周期的开始的池(或事件循环迭代),诸如鼠标按下事件,并在最后耗尽它,所以你的代码通常不必担心它们。有三种情况,不过,在这里你可以使用自己的自动释放池:

如果你正在编写一个不是基于应用程序套件,如命令行工具程序,没有内置支持用于autorelease池;你必须自己创建它们。

如果你产生了一个辅助线程,只要线程开始执行,你就必须创建你自己的自动释放池;否则,你会泄漏物体。 (详情请参阅“自动释放池和线程”。)

如果您编写一个可创建许多临时对象的循环,则可以在循环内部创建一个自动释放池,以在下一次迭代之前处置这些对象。这可以帮助减少应用程序的最大内存占用量。

我会说不要打扰,只需要根据需要分配任何对象,然后在从方法返回之前释放它们。

此外,请参阅此post

0

NSAutoreleasePool类用于支持Cocoa的引用计数内存管理系统。自动释放池存储当池本身耗尽时发送释放消息的对象。

在引用计数的环境中(与使用垃圾回收的环境相反),NSAutoreleasePool对象包含已收到自动释放消息的对象,排空时向其中的每个对象发送释放消息。因此,将autorelease而不是release发送给对象会延长该对象的生命周期,至少在池本身耗尽之前(如果随后保留该对象,则可能会更长)。一个对象可以放入同一个池中多次,在这种情况下,每次将对象放入池中时都会收到一条释放消息。

在引用计数的环境中,Cocoa预计会有一个始终可用的自动释放池。如果池不可用,则自动释放的对象不会释放,并且会泄漏内存。在这种情况下,您的程序通常会记录适当的警告消息。

Application Kit在事件循环的每个循环的开始处的主线程上创建一个自动释放池,并在最后消耗它,从而释放处理事件时生成的任何自动释放对象。如果您使用应用套件,则通常不需要创建自己的池。但是,如果您的应用程序在事件循环中创建了大量临时自动释放对象,那么创建“本地”自动释放池以帮助最大限度地减少峰值内存占用可能会有所帮助。

您使用通常的alloc和init消息创建一个NSAutoreleasePool对象,并使用drain(或release)来处理它,以了解其差异,请参阅“Garbage Collection”。既然你不能保留一个自动释放池(或自动释放它,请参阅retain和autorelease),那么排除一个池最终会导致释放它。您应始终在自己创建的上下文中调用自动释放池(调用方法或函数或循环体)。有关更多详细信息,请参阅自动释放池。

每个线程(包括主线程)都维护自己的NSAutoreleasePool对象堆栈(请参阅“线程”)。当新的池被创建时,它们被添加到堆栈的顶部。当池被解除分配时,它们将从堆栈中移除。自动释放的对象被放置到当前线程的顶层自动释放池中。当线程终止时,它会自动耗尽与其自身相关的所有自动释放池。

+0

但是我应该在我的情况下创建池??? – 2011-04-07 12:03:57

+0

不需要创建 – 2011-04-07 12:15:57

1

通常,我只需要在创建线程时使用autorelease池。

您需要添加sqlite3_mprintf和sqlite3_free语句。

+ (int) GetCountOfItems: (NSString*) byColumn { 

     NSString* sqliteQuery = @"SELECT COUNT(*) FROM [Articles] WHERE %q = 1"; 
     char *sql = sqlite3_mprintf((char*)[sqliteQuery UTF8String], (char*)[byColumn UTF8String]); //Add this statement 
     sqlite3_stmt* stmt; 
     int articleCount = 0; 

     if(sqlite3_prepare_v2(database, sql, -1, &stmt, NULL) == SQLITE_OK) { 
      if(sqlite3_step(stmt) == SQLITE_ROW) 
       articleCount = sqlite3_column_int(stmt, 0); 
     } 
     else NSLog(@"Failed from GetCountOfItems. Error is: %c", sqlite3_errmsg(database)); 

     sqlite3_finalize(stmt); 
     sqlite3_free(sql); //Add this statement 

     return articleCount; 
    } 
+0

sqlite3_free(sql);为什么? – 2011-04-07 12:11:27

+0

释放char * sql。 – Michael 2011-04-07 12:15:04

+0

但我认为它在功能完成其工作时自行释放。 – 2011-04-07 12:46:09

3

如果此代码在主线程中执行,那么不,您不必。

如果这是在另一个线程执行,那么,是的,你必须。