我应该使用AutoreleasePool吗?

时间:2011-04-07 11:53:27

标签: iphone database sqlite allocation

大家好我有一个在我的应用程序中使用sqlite数据库的类。在这里你可以看到我写的一个功能。此函数必须获取列值中的项目数等于给定值。

 + (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 * pool = [[NSAutoreleasePool alloc] init]; ???? 它如何帮助我记忆?

4 个答案:

答案 0 :(得分:3)

如果在主线程中执行此代码,则不需要。

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

答案 1 :(得分:2)

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

  

Application Kit会在事件周期(或事件循环迭代)开始时自动创建一个池,例如鼠标按下事件,并在结束时将其耗尽,因此您的代码通常不必担心它们。但是,有三种情况可以使用您自己的自动释放池:

     

如果您正在编写一个不基于Application Kit的程序,例如命令行工具,则不存在对自动释放池的内置支持;你必须自己创造它们。

     

如果生成辅助线程,则必须在线程开始执行后立即创建自己的自动释放池;否则,你会泄漏物体。 (有关详细信息,请参阅“自动释放池和线程”。)

     

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

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

另请参阅此post

答案 2 :(得分:1)

通常,我只需要在创建线程时使用自动释放池。

您需要添加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;
    }

答案 3 :(得分:0)

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

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

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

Application Kit在事件循环的每个循环开始时在主线程上创建一个自动释放池,并在最后将其排出,从而释放处理事件时生成的任何自动释放的对象。如果您使用Application Kit,则通常不必创建自己的池。但是,如果您的应用程序在事件循环中创建了许多临时自动释放的对象,那么创建“本地”自动释放池以帮助最小化峰值内存占用量可能是有益的。

使用通常的alloc和init消息创建一个NSAutoreleasePool对象,并使用drain(或release)来处理它以了解其中的差异,请参阅“垃圾收集”。由于您无法保留自动释放池(或自动释放它 - 请参阅保留和自动释放),因此耗尽池最终会释放它。您应该始终在创建它的相同上下文(调用方法或函数或循环体)中排出自动释放池。有关详细信息,请参阅自动释放池。

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