1

wiki のサンプル コードをテストしたところ、OS X (Lion 10.7.3、Xcode 4.3.2) と Linux (手動でコンパイルしてインストール) の両方で、libdispatch が解放せずに大量のメモリを割り当てていることがわかりました。

このコードは、ログファイルへの 100_000 書き込みを呼び出すハンドラを使用して、SIGHUP シグナル ソースを作成します。ログへの書き込みは、シリアル キューに入れられます。

最初の実行では、通常のメモリ使用量 (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 に答える