[英]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 也出現此問題。
我找到了一些其他方法來做到這一點而沒有內存泄漏:
我不明白為什么這個簡單的路由會導致這個問題。 我在谷歌上搜索過這個,但一無所獲。
如何通過保持串行隊列和 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.