1

我一直在测试来自 wiki 的示例代码,发现 libdispatch 在 OS X(Lion 10.7.3、Xcode 4.3.2)和 Linux(手动编译和安装)中分配了大量内存而没有释放它。

该代码创建了一个 SIGHUP 信号源,其中包含一个调用 100_000 次写入日志文件的处理程序。对日志的写入在串行队列中排队。

第一次运行显示正常的内存使用情况(Linux 和 OS X 均为 8-9 MiB)。发送“kill -1”后,每次发送 SIGHUP 信号时,内存使用量都会增加 1-20MiB。

我试过用 -fobj-arc 编译,没有它,但结果是一样的。我删除了 br_log 函数中的 NSString 用法,但不存在泄漏:它在 libdispatch 内部的某个地方。

我尝试了 valgrind 和 Xcode Instruments,但没有发现任何泄漏。提前致谢,

//
//  main.m
//  test02
//
//  Created by Aldrin Martoq on 4/29/12.
//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//

#include <unistd.h>
#import <Foundation/Foundation.h>
#import <dispatch/dispatch.h>

static FILE *log_file = NULL;
static NSString *log_filename = @"/tmp/br.log";
static dispatch_queue_t log_queue;


void br_log(NSString *format, ...) {
    @autoreleasepool {
        va_list ap;
        va_start(ap, format);
        NSString *s = [[NSString alloc] initWithFormat:format arguments:ap];
        va_end(ap);

        if (log_file == NULL) {
            log_queue = dispatch_queue_create("cl.martoq.log_queue", NULL);

            log_file = fopen([log_filename cStringUsingEncoding:NSUTF8StringEncoding], "a");
            NSLog(@"Log file created: %@", log_filename);
        }

        dispatch_async(log_queue, ^{
            @autoreleasepool {
                const char *c = [s cStringUsingEncoding:NSUTF8StringEncoding];
                fputs(c, log_file);
                fputs("\n", log_file);
                fflush(log_file);
                [s release];
            }
        });
    }
}

void br_setup() {
    signal(SIGHUP, SIG_IGN);
    dispatch_source_t sig_src = dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, SIGHUP, 0, dispatch_get_main_queue());
    dispatch_source_set_event_handler(sig_src, ^{
        dispatch_async(dispatch_get_main_queue(), ^{
            printf("Caught SIGHUP\n");
            for (int i = 0; i < 100000; i++) {
                br_log(@"prueba: %d", i);
            }
        });
    });
    dispatch_resume(sig_src);
}


int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        NSLog(@"Hello, World!");
        br_setup();
        dispatch_main();
    }
    return 0;
}
4

1 回答 1

0

您如何衡量这种内存使用增长?我无法使用“堆”工具在 Mac OS X 上重现它。

您可能会看到 libdispatch 延续缓存的临时效果,这些是为每个 dispatch_async() 分配的小缓冲区,并以每个线程为基础进行缓存以提高速度。一旦临时调度工作线程退出(在您的示例中,至少在 Mac OS X 上是在 SIGHUP 后几秒钟),该缓存就会被释放。

另请注意,无需从源事件处理程序中 dispatch_async(),因为此时您已经在主队列中(源的目标队列)

顺便说一句,你已经在libdispatch-dev@lists.macosforge.org上问过这个问题,我已经在那里回复了,请不要同时在多个论坛上问同样的问题。

于 2012-04-30T19:12:14.513 回答