加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

objective-c – stringByAppendingString导致系统内存耗尽应用程

发布时间:2020-12-16 10:25:21 所属栏目:百科 来源:网络整理
导读:当我在“大”(37000行)文本文件上运行以下代码时,是否有人能指出我系统告诉我内存应用程序耗尽的方向? -(void) writeToFile: (NSString*)filePath withSeparator:(NSString*) fieldSep{NSString* completeFile = [[[NSString alloc] initWithString:@""] au
当我在“大”(37000行)文本文件上运行以下代码时,是否有人能指出我系统告诉我内存应用程序耗尽的方向?

-(void) writeToFile: (NSString*)filePath withSeparator:(NSString*) fieldSep{
NSString* completeFile = [[[NSString alloc] initWithString:@""] autorelease];
for(int i=0;i<[self numberOfRows];i++){
    printf("im at line number... %i of %in",i,[self numberOfRows]);
    for(int j=0;j<[self numberOfColumns];j++){
        completeFile = [completeFile stringByAppendingString:[self objectInRow:i column:j]];

        if(j<[self numberOfColumns]-1){
            //separator for all columns except last one
            completeFile = [completeFile stringByAppendingString:fieldSep];
        }
    }
        completeFile = [completeFile stringByAppendingString:@"n"];
}
NSError *error = nil;
[completeFile writeToFile:filePath atomically:NO
                 encoding:NSStringEncodingConversionAllowLossy error:&error];
if(error){
    NSLog(@"Error writing file at %@n%@",filePath,[error localizedFailureReason]);
}

}

我出于调试原因添加了printf,前面似乎有4000行,然后它慢慢减速…我的文件包含超过37000行,类似于这些:

1893-11-6   136 194 165

解决方法

使用工厂方法分配对象时,会将对象添加到autoreleasepool.自动释放池仅在您的IBAction返回后运行事件循环时耗尽.

这里的技巧是将循环的内容放在自己的autorelasepool中.

但我们先解决最大的问题.你应该在这里使用一个NSMutableString类,这将大大减少你需要创建的对象的数量.

我们将completeFile切换为NSMutableString,使用工厂方法构造,然后附加到它:

-(void) writeToFile: (NSString*)filePath withSeparator:(NSString*) fieldSep{
    NSMutableString* completeFile = [NSMutableString string];
    for(int i=0;i<[self numberOfRows];i++){
        printf("im at line number... %i of %in",[self numberOfRows]);
        for(int j=0;j<[self numberOfColumns];j++){
            [completeFile appendString:[self objectInRow:i column:j]];

            if(j<[self numberOfColumns]-1){
                //separator for all columns except last one
                completeFile appendString:fieldSep];
            }
        }
            [completeFile appendString:@"n"];
    }
    NSError *error = nil;
    [completeFile writeToFile:filePath atomically:NO
                     encoding:NSStringEncodingConversionAllowLossy error:&error];
    if(error){
        NSLog(@"Error writing file at %@n%@",[error localizedFailureReason]);
    }
}

但这留下了另一个问题.看到[self objectInRow:i column:j]?它(可能)仍然是一个自动释放的对象.那不会被清理干净.

我们可能已经使您的代码运行而不会崩溃,具体取决于数据的大小,但这是一个什么时候崩溃的问题.

要解决这个问题,我们需要引入自动释放池.我们每行和每列做一个.这可能看起来过多(事实上,在这种情况下,因为我们已经消除了外循环中的autoreleasepool使用),但自动释放池相当便宜.如果您正在对大量数据进行循环,那么这只是一种很好的做法.

您可以使用@autorelease块替换每个for块,例如:

for(int i=0;i<[self numberOfRows];i++){

附:

for(int i=0;i<[self numberOfRows];i++) @autoreleasepool {

这给了我们这段代码:

-(void) writeToFile: (NSString*)filePath withSeparator:(NSString*) fieldSep{
    NSMutableString* completeFile = [NSMutableString string];
    for(int i=0;i<[self numberOfRows];i++) @autoreleasepool {
        printf("im at line number... %i of %in",[self numberOfRows]);
        for(int j=0;j<[self numberOfColumns];j++) @autoreleasepool {
            [completeFile appendString:[self objectInRow:i column:j]];

            if(j<[self numberOfColumns]-1){
                //separator for all columns except last one
                completeFile appendString:fieldSep];
            }
        }
            [completeFile appendString:@"n"];
    }
    NSError *error = nil;
    [completeFile writeToFile:filePath atomically:NO
                     encoding:NSStringEncodingConversionAllowLossy error:&error];
    if(error){
        NSLog(@"Error writing file at %@n%@",[error localizedFailureReason]);
    }
}

不过最后一点.您在此处的错误检查不安全.未定义在成功时传入的错误指针会发生什么变化.

[completeFile writeToFile:filePath atomically:NO
                     encoding:NSStringEncodingConversionAllowLossy error:&error];
    if(error){
        NSLog(@"Error writing file at %@n%@",[error localizedFailureReason]);
    }

相反,你想要这个:

BOOL ok = [completeFile writeToFile:filePath atomically:NO
                     encoding:NSStringEncodingConversionAllowLossy error:&error];
    if(!ok){
        NSLog(@"Error writing file at %@n%@",[error localizedFailureReason]);
    }

那么,这应该做你想要的.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读