0

我和我的同事正在努力解决这个问题。我们要解析一个文件(定制的 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 循环,则在文件关闭并检查可用内存后,我的内存比以前少了. 在过去的一周里,它一直让我和我的同事疯狂地试图解决这个问题。

编辑::

- (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;
}

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

4

2 回答 2

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/ setbuf(fp, NULL)O FILE*。通常,stdio 通过分配一个缓冲区来缓冲数据,malloc以便它可以读取大块的文件数据,并且free当您调用fclose. 您正在关闭文件,所以这不应该泄漏,但以防万一它与您的内存测量有关,可能值得尝试使用无缓冲 I/O 以获得更清晰的结果。

于 2012-11-12T17:00:15.433 回答
0

我想我们已经想通了。问题在于 ios 使用的 Autorelease 池,它实际上会在需要时释放内存,应用程序已关闭,或者当某些东西实际上需要为释放设置的内存时才能实际释放。在将大量内存恢复到几乎开始的状态(例如,它从 230mb 开始,而我现在有 225)之后,注意到它。这是一个奇怪的错误,因为我们希望所有这些都在未标记为发布时立即发布,并在需要时准确发布。

于 2012-11-13T15:29:05.690 回答