内存分配问题,设备 iOS SDK 4.1 崩溃(线程 0 崩溃)

发布于 2024-09-25 20:32:56 字数 3598 浏览 5 评论 0原文

我有两个问题

1) 我的应用程序在设备上运行的前几次运行良好。然后在弹出第一个屏幕(选项卡栏)后它崩溃了。如果我将设备连接到我的 MAC,然后运行设备应用程序,它就可以工作(不是调试模式)。

我检查了崩溃日志,它崩溃了“EXC_BAD_ACCESS(SIGSEGV)”的原因,并且Thread0崩溃了。错误是NSAutorelease释放了一个已释放的对象。

2)我使用模拟器上的仪器运行该应用程序。它显示这个函数调用有很多泄漏。 这是示例代码。当我使用 Instruments 运行它时,它显示“setObject”行上有泄漏。

//A 类- NSObject 的子类

+(NSMutableDictionary *)Hello {

 NSMutableDictionary *dctONE = [[NSMutableDictionary alloc]initWithCapacity:0];
 NSMutableArray *arrKeys = [[NSMutableArray alloc] initWithCapacity:0];

    [arrKeys addObject:@"Object1"];
 [arrKeys addObject:@"Object2"];

    [dctONE setObject:[NSString stringWithFormat:@"dsfsdf"] forKey:[arrKeys          objectAtIndex:0]];
 [dctONE setObject:[NSString stringWithFormat:@"dsfsdf"] forKey:[arrKeys objectAtIndex:1]];

    [arrKeys release];
    return dctONE;

}

/// B 类

-(void)some_Function {
 NSMutableDictionary * dct = [A Hello];   //all declarations are done

 //do stuff with dct
 [dct release];
}

为什么它在“setObject”处泄漏?我正在正确释放一切,对吗?唯一的事情是 [NSString stringWithFormat:] 但这是自动释放对吗?

这让我发疯了吗?

这两个问题有关联吗? PS:它不会在 sim 上崩溃,奇怪的是,即使我将设备连接到 MAC 然后在设备上测试它也不会崩溃(不是调试,直接单击设备上的应用程序)

编辑:

-(NSMutableDictionary *) ExecuteDataSet:(NSString *)strQuery
{
    NSMutableDictionary  *dctResult = [[[NSMutableDictionary alloc] init] autorelease];
//  BOOL isSucess = FALSE;

const char *sql = [strQuery UTF8String];
sqlite3_stmt *selectStatement;

//prepare the select statement
int returnValue = sqlite3_prepare_v2(database, sql, -1, &selectStatement, NULL);
if(returnValue == SQLITE_OK)
{
    sqlite3_bind_text(selectStatement, 1, sql, -1, SQLITE_TRANSIENT);
    //loop all the rows returned by the query.
    NSMutableArray *arrColumns = [[NSMutableArray alloc] init];
    for (int i=0; i<sqlite3_column_count(selectStatement); i++) 
    {
        const char *st = sqlite3_column_name(selectStatement, i);
        [arrColumns addObject:[NSString stringWithCString:st encoding:NSUTF8StringEncoding]];
    }
    int intRow =1;
    while(sqlite3_step(selectStatement) == SQLITE_ROW)
    {
        NSMutableDictionary *dctRow = [[NSMutableDictionary alloc] init];
        for (int i=0; i<sqlite3_column_count(selectStatement); i++)                 
        {
            int intValue = 0;
            const char *strValue;
            switch (sqlite3_column_type(selectStatement,i)) 
            {
                case SQLITE_INTEGER:
                    intValue  = (int)sqlite3_column_int(selectStatement, i);
                    [dctRow setObject:[NSString stringWithFormat:@"%d",intValue] forKey:[arrColumns objectAtIndex:i]];                      
                    break;

                case SQLITE_TEXT:
                    strValue = (const char *)sqlite3_column_text(selectStatement, i);
                    [dctRow setObject:[NSString stringWithCString:strValue encoding:NSUTF8StringEncoding] forKey:[arrColumns objectAtIndex:i]];                     
                    break;

                default:
                    strValue = (const char *)sqlite3_column_value(selectStatement, i);
                    [dctRow setObject:[NSString stringWithCString:strValue encoding:NSUTF8StringEncoding] forKey:[arrColumns objectAtIndex:i]];
                    break;
            }

        }
        [dctResult setObject:[dctRow retain] forKey:[NSString stringWithFormat:@"Table%d",intRow]];
        intRow ++;
        [dctRow release];
    }
    [arrColumns release];
}
return dctResult;

}

I have two problems

1) My App works fine on the device the first few times its run. Then it crashes after the First screen pops up(Tab BAr). If i connect the device to my MAC and then run the device app it works(not debug mode).

I Checked the crash Logs, it crashed cos of "EXC_BAD_ACCESS (SIGSEGV)" and Thread0 crashed.The error was NSAutorelease released a deallocated Object.

2) I ran the app using instruments on the simulator. It show a lot of leaks on this function call.
Here is a sample code. When i run it using Instruments it shows a leak on the "setObject" line.

//class A- subclass of NSObject

+(NSMutableDictionary *)Hello {

 NSMutableDictionary *dctONE = [[NSMutableDictionary alloc]initWithCapacity:0];
 NSMutableArray *arrKeys = [[NSMutableArray alloc] initWithCapacity:0];

    [arrKeys addObject:@"Object1"];
 [arrKeys addObject:@"Object2"];

    [dctONE setObject:[NSString stringWithFormat:@"dsfsdf"] forKey:[arrKeys          objectAtIndex:0]];
 [dctONE setObject:[NSString stringWithFormat:@"dsfsdf"] forKey:[arrKeys objectAtIndex:1]];

    [arrKeys release];
    return dctONE;

}

/// class B

-(void)some_Function {
 NSMutableDictionary * dct = [A Hello];   //all declarations are done

 //do stuff with dct
 [dct release];
}

WHy does it Leak at "setObject"?? I am releasing everything properly right? Only thing is the [NSString stringWithFormat:] but that is autorelease right??

This is driving me Crazy?

Are the two problems related??
PS: It Doesnt crash on the sim, and strangely doesnt crash even when i connect my device to my MAC and then test it on device(not debugging, directly clicking the app on the device)

EDIT:

-(NSMutableDictionary *) ExecuteDataSet:(NSString *)strQuery
{
    NSMutableDictionary  *dctResult = [[[NSMutableDictionary alloc] init] autorelease];
//  BOOL isSucess = FALSE;

const char *sql = [strQuery UTF8String];
sqlite3_stmt *selectStatement;

//prepare the select statement
int returnValue = sqlite3_prepare_v2(database, sql, -1, &selectStatement, NULL);
if(returnValue == SQLITE_OK)
{
    sqlite3_bind_text(selectStatement, 1, sql, -1, SQLITE_TRANSIENT);
    //loop all the rows returned by the query.
    NSMutableArray *arrColumns = [[NSMutableArray alloc] init];
    for (int i=0; i<sqlite3_column_count(selectStatement); i++) 
    {
        const char *st = sqlite3_column_name(selectStatement, i);
        [arrColumns addObject:[NSString stringWithCString:st encoding:NSUTF8StringEncoding]];
    }
    int intRow =1;
    while(sqlite3_step(selectStatement) == SQLITE_ROW)
    {
        NSMutableDictionary *dctRow = [[NSMutableDictionary alloc] init];
        for (int i=0; i<sqlite3_column_count(selectStatement); i++)                 
        {
            int intValue = 0;
            const char *strValue;
            switch (sqlite3_column_type(selectStatement,i)) 
            {
                case SQLITE_INTEGER:
                    intValue  = (int)sqlite3_column_int(selectStatement, i);
                    [dctRow setObject:[NSString stringWithFormat:@"%d",intValue] forKey:[arrColumns objectAtIndex:i]];                      
                    break;

                case SQLITE_TEXT:
                    strValue = (const char *)sqlite3_column_text(selectStatement, i);
                    [dctRow setObject:[NSString stringWithCString:strValue encoding:NSUTF8StringEncoding] forKey:[arrColumns objectAtIndex:i]];                     
                    break;

                default:
                    strValue = (const char *)sqlite3_column_value(selectStatement, i);
                    [dctRow setObject:[NSString stringWithCString:strValue encoding:NSUTF8StringEncoding] forKey:[arrColumns objectAtIndex:i]];
                    break;
            }

        }
        [dctResult setObject:[dctRow retain] forKey:[NSString stringWithFormat:@"Table%d",intRow]];
        intRow ++;
        [dctRow release];
    }
    [arrColumns release];
}
return dctResult;

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

睡美人的小仙女 2024-10-02 20:32:56

泄漏似乎在这一行:

[dctResult setObject:[dctRow retain] forKey:[NSString stringWithFormat:@"Table%d",intRow]];

setObject will call retain on the object itstores, but you 实际上是手动保留它,所以它的保留计数将是 2 而不是1,当dctResult被释放时,它不会从内存中删除。

The leak appears to be in this line:

[dctResult setObject:[dctRow retain] forKey:[NSString stringWithFormat:@"Table%d",intRow]];

setObject will call retain on the object it stores, but you are actually retaining it manually, so its retain count will be 2 instead of 1, and when dctResult gets released, it won't be removed from memory.

聆听风音 2024-10-02 20:32:56

您在 +Hello 中做了一大堆不必要的工作。我调试的第一步始终是消除不必要的复杂性。尝试像这样:

+(NSMutableDictionary *)Hello {

     NSMutableDictionary *dctONE = [NSMutableDictionary dictionaryWithObjectsAndKeys:
         @"dsfsdf", @"Object1", @"dsfsdf", @"Object2", nil];

     return dctONE;
}

NSMutableDictionary DictionaryWithObjectsAndKeys 方法采用一个以 nil 结尾的数组,该数组包含对象、键、对象、键。它返回一个自动释放的 NSMutableDictionary 对象,这就是您想要返回的对象。

这个世界上没有任何保证,但我几乎可以向你保证该方法不会泄漏。

You're doing a whole bunch of unnecessary work in +Hello. My first step at debugging is always to remove unnecessary complexity. Try it like this:

+(NSMutableDictionary *)Hello {

     NSMutableDictionary *dctONE = [NSMutableDictionary dictionaryWithObjectsAndKeys:
         @"dsfsdf", @"Object1", @"dsfsdf", @"Object2", nil];

     return dctONE;
}

That NSMutableDictionary dictionaryWithObjectsAndKeys method takes a nil-terminated array that goes object, key, object, key. It returns an autoreleased NSMutableDictionary object, which is what you want to be returning.

There are no guarantees in this world, but I can darn near promise you that method won't leak.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文