Проблема
Ознакомьтесь со следующим консольным приложением macOS и советами, как предотвратить рост (утечку) следа памяти, вызванный SecItemCopyMatching:
...
let service = "SampleService"
func composeQuery() -> [String: Any] {
return [kSecClass as String: kSecClassInternetPassword,
kSecAttrServer as String: service,
kSecMatchLimit as String: kSecMatchLimitOne,
kSecReturnAttributes as String: true,
kSecReturnData as String: true]
}
func save(value: String) {
let encodedValue = value.data(using: String.Encoding.utf8)!
var query = composeQuery()
query[kSecValueData as String] = encodedValue
SecItemAdd(query as CFDictionary, nil)
}
autoreleasepool {
save(value: "SomeValue")
}
for _ in 0..<20000 {
let query = composeQuery()
//continue // UNCOMMENT here - no leak
_ = autoreleasepool {
//######################
// THE PROBLEM IS HERE
//######################
SecItemCopyMatching(query as CFDictionary, nil)
//######################
// THE END
//######################
}
}
...
Нет утечек в соответствии с приборами. Но в Activity Monitor я вижу, что объем памяти продолжает расти, и почти все будет меняться.
Согласно vmmap:
VIRTUAL RESIDENT DIRTY SWAPPED VOLATILE NONVOL EMPTY REGION
REGION TYPE SIZE SIZE SIZE SIZE SIZE SIZE SIZE COUNT (non-coalesced)
VM_ALLOCATE 78.1M 0K 0K 78.1M 0K 0K 0K 647
По моим наблюдения каждый SecItemCopyMatching стоит ок. 4 КБ утечек (заброшенных и замененных) памяти. Поэтому, если вы увеличите число основных итераций l oop с 20 000 до 200 000 =>, вы увидите ~ 800 МБ утечки памяти.
Что не так с использованием SecItemCopyMatching?
Чтобы создать и запустите KeychainLeak
Вы можете проверить образец самостоятельно. Для удобства я поставил код здесь:
https://github.com/botov/KeychainOSXLeak