【问题标题】:Custom Class + Database calls causing memory to rise?自定义类 + 数据库调用导致内存上升?
【发布时间】:2011-12-04 19:30:30
【问题描述】:

这是对前面两个问题的补充。我正在使用 heapshots 来检查我的内存在提交到应用商店之前的表现,我发现每次用户完成程序循环时它都会增加 3-5KB。我回到绘图板上,注释掉程序的大部分内容,然后慢慢将这些部分重新上线。我能够将其范围缩小到我认为是问题的核心。

我会注意:我转换为 ARC 后仍然遇到同样的问题。这里(我相信)是相关的代码区域。

行类:

@interface Row : NSObject {
int rowID;
NSString *rowProblem;
NSString *rowAnswer;
int rowTimes_Right;
int rowTimes_Wrong;
Boolean marked;
}

@property (nonatomic) int rowID;
@property (nonatomic, copy) NSString *rowProblem;
@property (nonatomic, copy) NSString *rowAnswer;
@property (nonatomic) int rowTimes_Wrong;
@property (nonatomic) int rowTimes_Right;
@property (nonatomic) Boolean marked;

数据库函数(获取一行):

-(Row *) getRow {
Row *holder = [[[Row alloc] init] autorelease];

//Pick a random problem to give to the User
int randomrow = (arc4random() % [self getNumberOfRows]) + 1;



NSString *querysql = [NSString stringWithFormat:@"SELECT * FROM problems WHERE id = %d", randomrow];

const char *sql = [querysql UTF8String];    
sqlite3_stmt *statement;

//Execute the Query
if (sqlite3_prepare_v2(wordsDB, sql, -1, &statement, NULL) == SQLITE_OK)
{

    while (sqlite3_step(statement) == SQLITE_ROW) 
    {
        char *problem = (char *)sqlite3_column_text(statement, 1);
        char *answer = (char *)sqlite3_column_text(statement, 2);

        holder.rowID = sqlite3_column_int(statement, 0);
        holder.rowProblem = [NSString stringWithUTF8String:problem];
        holder.rowAnswer = [NSString stringWithUTF8String:answer];
        holder.rowTimes_Right = sqlite3_column_int(statement, 3);
        holder.rowTimes_Wrong = sqlite3_column_int(statement, 4);
        holder.marked = sqlite3_column_int(statement, 5);

    }

    sqlite3_finalize(statement);
}
else
{
    NSLog(@"SQL Error Message: %s", sqlite3_errmsg(wordsDB));
}

return holder;
}

在视图中将它们捆绑在一起:

-(void)setToWord{
[currentRow release];
 currentRow = [[dataB getRow] retain];

[problemLabel setText:currentRow.rowProblem];
[definitionLabel setText:currentRow.rowAnswer];
}

任何想法将不胜感激。

【问题讨论】:

  • 肯定 heapshot 会准确地告诉你什么,什么时候增加?
  • @hooleyhoop 确实如此,我在之前的问题中询问了具体部分(包括发布调用堆栈),但没有人能破译它。

标签: ios class memory-management


【解决方案1】:

我不会担心 5KB 的泄漏。 Apple 自己的 Cocoa 例程漏洞到了这个程度,Apple 显然并不担心。例如,在我的一个简单应用程序中,我们将视图控制器推到导航控制器上,然后再次将其弹出,仪器显示我的所有对象都已正确拆除,但有轻微泄漏,显然来自内部深处可可。您应该能够使用 Instruments 非常清楚地看到生成每个 heapshot 中剩余的对象的代码是否是您的代码。您可以尝试将 getRow 方法的内部包裹在 @autoreleasepool{} 中,但我怀疑这会有所不同。

【讨论】:

  • 所以如果我提交了我的程序,苹果就不会担心这个吗? Leaks 没有发现任何东西,Analyzer 也没有,但我担心他们会看到幕后的泄漏并拒绝。
  • 我提交了上面描述的应用程序,没有任何问题。 - 事实上,试试这个;从 Xcode 的内置 Utility Application 模板制作一个应用程序并在 Instruments 下运行它。做一个显示当您翻转到模态视图并向后翻转时会发生什么的快照。你会看到一个很小的泄漏,大约 6KB。苹果的代码充满了这些东西。每轮 5KB 是!我们生活在一个 GB 的世界中。
  • Apple 不会因此拒绝您的应用程序。修复它仍然很好,因为内存泄漏最终会导致您的应用程序被杀死。多久取决于您泄漏内存的速度,以及您实际执行任务时使用的内存量。顺便说一句,泄漏是否显示内存已泄漏?如果不是,则可能是缓存对象,可能会在内存警告时释放。
【解决方案2】:

好吧,这经常令人沮丧。在您之前的两个问题中,您都发布了详细的堆栈跟踪。这是 Instruments 向您展示的不太有趣的事情之一。

在你的程序中选择任何一点——当它运行时它使用内存——这就是堆栈,你不需要 Instruments 来告诉你。

仪器可以向您显示应用中所有活动对象的数量 - 从堆到堆增加了哪些不该增加的?可能会意外地让您认为已被破坏、徘徊、泄漏的对象,但不会出现在泄漏中,因为从技术上讲,它们仍然可以从某个地方到达。如果您发现一个正在泄漏或不应该存在的对象,那么重要的不是创建它的行的堆栈跟踪,而是为什么没有清理它?你在哪里忘记释放或释放? Instruments 将向您显示每个对象的保留历史记录,以便您找出未平衡保留或清理属性的位置。

这只是基本的 Instruments 东西,真的很容易被我学会。

作为旁注。尽管框架有时确实很少发生泄漏,但对我来说,更常见的错误会在泄漏中表现为一个字节块在某些框架中被深度泄漏。

【讨论】:

    猜你喜欢
    • 2020-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多