2016-02-29 3 views
1

У меня есть C char *cArray и его длина, и мне нужно, чтобы преобразовать его в NSData Я сделал это с:NSData причиной утечки

var data: NSData? = NSData(bytesNoCopy: cArray, length: Int(length)) 

И это работает. Проблема в том, что это вызывает некоторую утечку памяти. Я не знаю, почему, но я могу видеть, что в средствах выделения это malloc 64 байта и не освобождает его, когда функция заканчивается, или когда я устанавливаю ее на нуль.

Этот код называется много, поэтому мне нужно, чтобы он был бездействующим. Что я могу сделать, чтобы предотвратить утечку?

Edit: это код

func on_data_recv_fn(buf: UnsafeMutablePointer<CChar>, length: CInt, user_data: UnsafeMutablePointer<Void>) -> CInt { 
    guard buf != nil else { 
     NSLog("on_data_recv_fn buf is nil") 
     return -1 
    } 

    //var data: NSData? = NSData(bytesNoCopy: buf, length: Int(length), freeWhenDone: true) 
    var data: NSData? = NSData(bytesNoCopy: buf, length: Int(length)) 
    let succeededWriting = Int(PacketTunnelProvider.sendPackets(data!)) 
    data = nil 
    return CInt(succeededWriting) 
} 

Согласно документам памяти, есть утечка здесь. Функция sendPackets не хранит данные, поэтому проблемы там нет.

Редактировать: Прикрепленное изображение с инструментов. instruments image

+0

Полный способ код пожалуйста. – Darko

+0

См. Отредактированный ответ – Roee84

+1

Что произойдет, если вы вызываете предупреждение о памяти? Выпущена ли память? – Darko

ответ

2

Ну, похоже, что если я использую autoreleasepool, все по какой-то причине.

1

Управление памятью типов, поддерживаемых Objective-C, представляет собой обширную и интересную тему. Смотрите, например, здесь:

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/WorkingWithCocoaDataTypes.html

Вы также можете найти этот вопрос полезным:

Is it necessary to use autoreleasepool in a Swift program?

Кроме того, я думаю, что есть опасность здесь, если buf передается on_data_recv_fn была динамически выделенный некоторым кодом C, который затем пытается освободить его. Другая опасная возможность: функция - это обратный вызов, реализованный в Swift и вызываемый кодом C. В этом случае buf может быть в стеке.

Я не играл ни с одним из этих сценариев, но в соответствии с NSData документации, то bytesNoCopy инициализатор делает NSData взять на себя ответственность памяти, а затем де-выделить его; предполагается, что память была выделена с использованием malloc(), поэтому любая память, которая не была malloc'd, не должна использоваться для построения NSData с использованием этого инициализатора. См. https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSData_Class/#//apple_ref/occ/instm/NSData/initWithBytesNoCopy:length:

Есть и другие инициализаторы NSData, которые делают копию буфера и могут быть более безопасными в этих случаях.

Смежные вопросы