为什么fread不会在ios上释放内存

时间:2012-11-12 16:14:16

标签: ios c memory-leaks fread

我的同事和我正在试图找出这个问题的杀手。 我们想要解析一个文件(自定义的3d对象文件)。问题在于使用stdio函数调用,如fread,fseek等。

在下面的代码中,当我在通话前和通话后检查虚拟内存时,每次运行该功能时我都会丢失1MB,我不知道为什么会这样。

FILE *fp= fopen([path UTF8String], "rb");
char *buffer = (char *) malloc(MAX_STRING_LENGTH);
while(!feof(fp))
{
    fgets(buffer, MAX_STRING_LENGTH, fp);
}

if(0 == fclose(fp))
    NSLog(@"File is closed");

free(buffer)

路径是从ios库生成的,MAX_STRING_LENGTH是一个任意大的数字(例如2000000)

在示例中也使用了http://www.cplusplus.com/reference/clibrary/cstdio/fread/中的函数,但内存错误仍然存​​在。

我知道缓冲区不是问题,因为如果我使用只是创建缓冲区并释放它然后没有采取内存但是如果我使用while循环然后文件关闭后我检查可用内存我少了一个MB比以前。它一直在推动我和我的同事疯狂地试图解决这个问题。

EDIT ::

- (float)print_usage_memory
{    
vm_statistics_data_t vmStats;
mach_msg_type_number_t infoCount = HOST_VM_INFO_COUNT;
host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vmStats, &infoCount);

const int availablePages = vmStats.free_count;
float availableMemory = [self pagesToMB:availablePages];

/*
 */     
const int totalPages = vmStats.wire_count + vmStats.active_count + vmStats.inactive_count + vmStats.free_count;
const int activePages = vmStats.active_count;
const int wiredPages = vmStats.wire_count;
const int purgeablePages = vmStats.purgeable_count;   

NSMutableString* txt = [[NSMutableString alloc] initWithCapacity:512];
[txt appendFormat:@"\nTotal: %d (%.2fMB)\n", totalPages, [self pagesToMB:totalPages]];
[txt appendFormat:@"                              nAvailable: %d (%.2fMB)\n", availablePages, availableMemory];
[txt appendFormat:@"                                 nActive: %d (%.2fMB)\n", activePages, [self pagesToMB:activePages]];
[txt appendFormat:@"nWired: %d (%.2fMB)\n", wiredPages, [self pagesToMB:wiredPages]];
[txt appendFormat:@"nPurgeable: %d (%.2fMB)\n", purgeablePages, [self pagesToMB:purgeablePages]];

NSLog(@"%@", txt);
[txt release];
txt = nil;

return availableMemory;
}


- (float)pagesToMB:(const int)pages
{
    return pages*4/1024;
}

感谢您提供的任何帮助或对此的任何见解。

2 个答案:

答案 0 :(得分:0)

一些想法:

  1. 如果您在循环中运行测试,请确保在循环内排出自动释放池。否则,在测试之前它不会被耗尽,并且会使测量结果变得混乱。例如:

    for(int i = 0; i < TEST_COUNT; i++)
    {
        // If you're using ARC, you can instead replace this with an
        // @autoreleasepool block
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        run_my_fopen_fgets_fclose_test();
        [pool release];
    }
    
  2. 尝试使用无缓冲的I / O,打开后立即调用FILE*对象上的setbuf(fp, NULL)。通常,stdio通过分配具有malloc的缓冲区来缓冲数据,以便它可以以大块读取文件数据,并且当您调用free时,此缓冲区将被fclose取消分配。你正在关闭文件,所以这不应该泄漏,但是为了防止你的内存测量结果,可能值得尝试使用无缓冲的I / O来获得更清晰的结果。

答案 1 :(得分:0)

我认为我们已经弄明白了。问题在于ios使用的自动释放池实际上是在它想要时,关闭应用程序,以及什么时候实际需要释放的内存实际释放时释放内存。在获得大量内存(大约3mb左右)到几乎它开始时(例如,它以230mb开始,我现在有225)之后,注意到它。这是一个奇怪的错误,因为我们预计所有这些都会在未标记为发布时立即发布,并在需要时进行实际发布。