内存分配问题,设备 iOS SDK 4.1 崩溃(线程 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
泄漏似乎在这一行:
setObject
will callretain
on the object itstores, but you 实际上是手动保留它,所以它的保留计数将是 2 而不是1,当dctResult
被释放时,它不会从内存中删除。The leak appears to be in this line:
setObject
will callretain
on the object it stores, but you are actually retaining it manually, so its retain count will be 2 instead of 1, and whendctResult
gets released, it won't be removed from memory.您在
+Hello
中做了一大堆不必要的工作。我调试的第一步始终是消除不必要的复杂性。尝试像这样: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: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.