簡體   English   中英

在 dispatch_async 中執行簡單的 malloc/free 會導致 iOS9 上的內存泄漏

[英]Doing simple malloc/free within dispatch_async causes memory leak on iOS9

將 iPad 更新到 iOS9 后,我的代碼出現內存泄漏,這在 iOS8 和 iOS7 上運行良好。

我有一個由以下代碼創建的匿名線程:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
    [self threadWork];
});

該線程執行一對 malloc/free 調用,如下所示:

- (void)threadWork {
    // Create a serial queue.
    dispatch_queue_t mySerialQueue = dispatch_queue_create("myQueue", NULL);

    while (1) {
        // Do a simple malloc.
        int *foo = (int *)malloc(1024);

        // Do free in serial queue.
        dispatch_async(mySerialQueue, ^{
            free(foo);
        });

        [NSThread sleepForTimeInterval:1.0 / 60.0];
    }
}

此路由將保持內存使用量增加並最終導致 iOS 9 上的設備崩潰。 Objective-C++ 中的 new/delete 也出現此問題。


我找到了一些其他方法來做到這一點而沒有內存泄漏:

  1. 使用主隊列或全局隊列代替串行隊列。
  2. 創建並發隊列而不是串行隊列。
  3. 使用 [NSThread detachNewThreadWithSelector:toTarget:withObject:] 代替 GCD 創建線程。

我不明白為什么這個簡單的路由會導致這個問題。 我在谷歌上搜索過這個,但一無所獲。

如何通過保持串行隊列和 GCD 匿名線程來做到這一點?


更新:

我試圖將 NSLog 命令放入我的代碼中,以確定何時會調用 malloc/free。 結果顯示,它們兩個都被立即調用並成對出現。 我還嘗試將線程減慢到每秒一次,但問題仍然存在。

線程測試代碼:

- (void)threadWork {
    uint64_t mallocCount = 0;
    __block uint64_t freeCount = 0;
    dispatch_queue_t mySerialQueue = dispatch_queue_create("MyQueue", NULL);
    while (1) {
        void *test = malloc(1024);
        NSLog(@"malloc %llu", ++mallocCount);
        dispatch_async(mySerialQueue, ^{
            free(test);
            NSLog(@"free %llu", ++freeCount);
        });
        [NSThread sleepForTimeInterval:1.0];
    }
}

控制台結果:

...
2015-10-23 09:51:33.876 OS9MemoryTest[759:153135] malloc 220
2015-10-23 09:51:33.876 OS9MemoryTest[759:153133] free 220
2015-10-23 09:51:34.877 OS9MemoryTest[759:153135] malloc 221
2015-10-23 09:51:34.878 OS9MemoryTest[759:153133] free 221
2015-10-23 09:51:35.883 OS9MemoryTest[759:153135] malloc 222
2015-10-23 09:51:35.883 OS9MemoryTest[759:153133] free 222

我想我已經找到了一種更好的方法來做到這一點而沒有泄漏問題,而不是使用 dispatch_sync。

重點似乎是串行隊列的服務質量 (QoS) 類的設置。 在具有 QOS_CLASS_UNSPECIFIED QoS 類的隊列中執行空閑會導致此問題。


在我的問題中,我在由以下調用創建的串行隊列中釋放內存:

dispatch_queue_t mySerialQueue = dispatch_queue_create("MyQueue", NULL);

它的 QoS 設置是 QOS_CLASS_UNSPECIFIED,這會導致此問題。

如果使用dispatch_queue_attr_t對象創建一個串行隊列,除了QOS_CLASS_UNSPECIFIED之外,還有QoS設置,代碼運行完美無泄漏:

- (void)threadWork {
    // Create a serial queue with QoS class.
    dispatch_queue_attr_t attr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, 0);
    dispatch_queue_t mySerialQueue = dispatch_queue_create("myQueue", attr);

    while (1) {
        // Do a simple malloc.
        int *foo = (int *)malloc(1024);

        // Do free in serial queue.
        dispatch_async(mySerialQueue, ^{
            free(foo);
        });

        [NSThread sleepForTimeInterval:1.0 / 60.0];
    }
}

我仍然不明白為什么在 iOS9 上會發生這個問題,但是設置 QoS 似乎可以使事情起作用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM