2011-04-07 103 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

如果此代碼在主線程中執行,那麼不,您不必。

如果這是在另一個線程執行,那麼,是的,你必須。