A memory leak when capturing callback function from block of setTerminationHandler of NSTask

Hi @eskimo and experts,

I created a simple code and found there is a memory leak:

#import <Foundation/Foundation.h>
#include <functional>
void testLeaks(const std::function <void (int)>& inCallback) {
  NSTask* task = [[NSTask alloc] init];
  [task setTerminationHandler:^(NSTask* inTask) {
    inCallback(inTask.terminationStatus);
  }];
   
  [task release];
}
int main(int argc, const char * argv[]) {
  auto callback = [](int result) {
    NSLog(@"callback");
  };
  testLeaks(callback);
  NSLog(@"done");
  return 0;
}

The output of leaks:

Process: testLeaks2 [13084]
Path: /Users/USER/Library/Developer/Xcode/DerivedData/Build/Products/Debug/testLeaks2
Load Address: 0x10a04d000
Identifier: testLeaks2
Version: ???
Code Type: X86-64
Platform: macOS
Parent Process: leaks [13083]
Date/Time: 2022-02-28 23:34:28.374 +0800
Launch Time: 2022-02-28 23:34:27.939 +0800
OS Version: Mac OS X 10.15.6 (19G73)
Report Version: 7
Analysis Tool: /Applications/Xcode.app/Contents/Developer/usr/bin/leaks
Analysis Tool Version: Xcode 12.4 (12D4e)
----
leaks Report Version: 4.0
Process 13084: 596 nodes malloced for 59 KB
Process 13084: 1 leak for 48 total leaked bytes.
1 (48 bytes) ROOT LEAK: <__NSMallocBlock__ 0x7fbbc2704350> [48] testLeaks2 invocation function for block in testLeaks(std::__1::function<void (int)> const&) 0..."

Looks the issue is in the block of setTerminationHandler. How do I address this memory leak issue if I want to keep using std::function as a callback?

Answered by DTS Engineer in 706480022

just found if any variable even primitive types captured by the block of -setTerminationHandler, then there is a leak

Well, that makes it quite clear that this is a bug, and I’d appreciate you filing it as such.

Please post your bug number, just for the record.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

just found if any variable even primitive types captured by the block of setTerminationHandler, then there is a leak:

void testLeaks() {
   int abc = 123;
NSTask* task = [[NSTask alloc] init];
[task setTerminationHandler:^(NSTask* inTask) {
NSLog(@"setTerminationHandler %d %d", inTask.terminationStatus, abc);
   }];
   [task release];
}

The output is the same:

Process 10635: 593 nodes malloced for 59 KB
Process 10635: 1 leak for 48 total leaked bytes.
1 (48 bytes) ROOT LEAK: <__NSMallocBlock__ 0x7f935ed09690> [48] testLeaks2 invocation function for block in testLeaks() 0x10a6a27e0
Accepted Answer

just found if any variable even primitive types captured by the block of -setTerminationHandler, then there is a leak

Well, that makes it quite clear that this is a bug, and I’d appreciate you filing it as such.

Please post your bug number, just for the record.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thanks a lot, @eskimo. Please refer to FB9942875.

A memory leak when capturing callback function from block of setTerminationHandler of NSTask
 
 
Q