swiftlang / swift-corelibs-foundation

The Foundation Project, providing core utilities, internationalization, and OS independence
swift.org
Apache License 2.0
5.3k stars 1.14k forks source link

[SR-1552] NSMutableData(capacity:) memory leak on Linux #4349

Closed swift-ci closed 7 years ago

swift-ci commented 8 years ago
Previous ID SR-1552
Radar None
Original Reporter djones6 (JIRA User)
Type Bug
Status Closed
Resolution Done
Environment Linux environment: Ubuntu 14.04.4 LTS, Lenovo x3550 M5 server (Intel Xeon E5-2640 v3), 192gb RAM Mac environment: OS X 10.11.4, Mac Mini, 4gb RAM Swift version: DEVELOPMENT-SNAPSHOT-2016-05-03-a
Additional Detail from JIRA | | | |------------------|-----------------| |Votes | 0 | |Component/s | Foundation | |Labels | Bug, Leak | |Assignee | mbvreddy (JIRA) | |Priority | Medium | md5: f0f72053f93dc08bf9b7e24d7ef1fdeb

Issue Description:

The following code leaks memory on Linux. It does not leak on Mac.

swift-ci commented 8 years ago

Comment by Bhaktavatsal Reddy (JIRA)

Memory that leaks here is NSData._bytes which is cleared by either custom deallocHandler or __CFDataDeallocate which is called as part of de-initialization sequence. Below is deint block of NSData

deinit {
if let allocatedBytes = _bytes {
_deallocHandler?.handler(allocatedBytes, _length)
}
if self.dynamicType === NSData.self || self.dynamicType === NSMutableData.self {
_CFDeinit(self._cfObject)
}
}

NSData._bytes is initialized using _CFDataInit(CFMutableDataRef memory, CFOptionFlags flags, CFIndex capacity, const uint8_t *bytes, CFIndex length, Boolean noCopy) function. This function either reuse the incoming bytes pointer or allocate new memory and copy contents from incoming bytes based on last argument 'noCopy' value.

NSData initialized with noCopy (= true) with options flag (__kCFDontDeallocate) explicitly tells __CFDataDeallocate not to clear the memory and will be taken care by deallocHandler. So, if __kCFDontDeallocate bit is set on NSData object, NSData._bytes is not freed by __CFDataDeallocate.

Current implementation set __kCFDontDeallocate in all cases even when incoming flags do not contain it. This makes __CFDataDeallocate not to free NSData._bytes resulting in leak.

To fix leak, check for incoming flags for __kCFDontDeallocate and set InfoBits of NSData accordingly.

swift-ci commented 8 years ago

Comment by Bhaktavatsal Reddy (JIRA)

created PR https://github.com/apple/swift-corelibs-foundation/pull/380

swift-ci commented 7 years ago

Comment by David Jones (JIRA)

This was resolved by the PR that Bhakta submitted.