import Foundation while true { var myData: NSMutableData? = NSMutableData(capacity: 0) myData = nil }
Running this infinite loop with swift-corelibs-foundation shows a steady memory leak, with the process's RSS increasing over time. No leak is seen with Foundation on Darwin. Instrumenting with Valgrind's massif profiler shows this stacktrace is responsible for the leak: 67.36% (114,349B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc. ->65.01% (110,352B) 0x59F7A89: _CFDataInit ->65.01% (110,352B) 0x5B8A8DF: _TTSf4n_n_n_g_n___TFC10Foundation6NSDatacfT5bytesGSqGSpT___6lengthSi4copySb11deallocatorGSqFTGSpT__Si_T___S0_ ->65.01% (110,352B) 0x5B873ED: _TFC10Foundation13NSMutableDataCfT8capacitySi_GSqS0__ ->65.01% (110,352B) 0x40105D: main I've stepped through the code with a debugger and observed that the requested capacity is thrown away <https://github.com/apple/swift-corelibs-foundation/blob/df239bbbdf5bcdd9ea31c394c6af4dd7c328f99d/Foundation/NSData.swift#L904> [1] to begin with. The leak occurs regardless of the capacity requested. The deinitializer for NSData does call through to _CFDeinit(), which does then call the finalize() <https://github.com/apple/swift-corelibs-foundation/blob/ea6179dd35be2c7d9a8f953579f626a5f1be6511/CoreFoundation/Base.subproj/CFRuntime.c#L1773> [2] function and hence through to __CFDataDeallocate() <https://github.com/apple/swift-corelibs-foundation/blob/ea3014bd7883e428727272118cbf37dc56522be6/CoreFoundation/Collections.subproj/CFData.c#L294> [3]. However, once in __CFDataDeallocate(), the code to free the buffer is skipped, because __kCFDontDeallocate is set. If I hack _CFDataInit() so that __kCFDontDeallocate isn't set (by commenting out this line <https://github.com/apple/swift-corelibs-foundation/blob/ea3014bd7883e428727272118cbf37dc56522be6/CoreFoundation/Collections.subproj/CFData.c#L337> [4]) then I get crashes elsewhere - so this obviously isn't the right approach. I can see that some work has been done in this area <https://github.com/apple/swift-corelibs-foundation/commit/ea3014bd7883e428727272118cbf37dc56522be6> [5] previously by Philippe so I'm wondering if anyone can advise on what might be going on here? The init?(length:) initializer avoids CFData entirely and calls malloc() and free() directly. I'm not sure why that approach was taken and whether it's relevant to my issue. Any help would be gratefully received! Thanks, [1] https://github.com/apple/swift-corelibs-foundation/blob/df239bbbdf5bcdd9ea31c394c6af4dd7c328f99d/Foundation/NSData.swift#L904 [2] https://github.com/apple/swift-corelibs-foundation/blob/ea6179dd35be2c7d9a8f953579f626a5f1be6511/CoreFoundation/Base.subproj/CFRuntime.c#L1773 [3] https://github.com/apple/swift-corelibs-foundation/blob/ea3014bd7883e428727272118cbf37dc56522be6/CoreFoundation/Collections.subproj/CFData.c#L294 [4] https://github.com/apple/swift-corelibs-foundation/blob/ea3014bd7883e428727272118cbf37dc56522be6/CoreFoundation/Collections.subproj/CFData.c#L337 [5] https://github.com/apple/swift-corelibs-foundation/commit/ea3014bd7883e428727272118cbf37dc56522be6 -- Ian Partridge
_______________________________________________ swift-corelibs-dev mailing list swift-corelibs-dev@swift.org https://lists.swift.org/mailman/listinfo/swift-corelibs-dev