通过VTDecompressionSessionDecodeFrame传UnsafeMutableRawPointer报EXC_BAD_ACCESS如何解决
问题根本原因
你遇到的EXC_BAD_ACCESS崩溃根源是:传给frameRefcon的是栈上局部变量的地址,VTDecompressionSessionDecodeFrame为异步调用,解码回调触发时,局部变量cString已经超出作用域被系统回收。前几次能正常打印只是巧合——对应的栈内存还没被其他数据覆盖,等到栈内存被复用就会触发野指针访问崩溃。
正确的实现方案
需要手动管理对象生命周期,把堆上对象的指针传给frameRefcon,标准实现分两步:
1. 传参侧代码
将字符串对象手动retain后,把原始指针传入接口:
let string = "Test" let nsString = string as NSString // 手动持有对象,所有权转移给指针,不会被ARC自动释放 let frameRefcon = Unmanaged.passRetained(nsString).toOpaque() VTDecompressionSessionDecodeFrame( decompressionSession, sampleBuffer: sampleBuffer, flags: [ ._EnableAsynchronousDecompression, ._EnableTemporalProcessing], frameRefcon: frameRefcon, infoFlagsOut: &flagsOut)
2. 回调侧代码
读取对象后手动释放,平衡引用计数避免内存泄漏:
callback = { (decompressionOutputRefCon: UnsafeMutableRawPointer?, sourceFrameRefCon: UnsafeMutableRawPointer?, status: OSStatus, infoFlags: VTDecodeInfoFlags, imageBuffer: CVBuffer?, presentationTimeStamp: CMTime, duration: CMTime) in if let sourceFrameRefCon = sourceFrameRefCon { // 读取对象同时自动释放之前手动持有的内存,平衡引用计数 let nsString = Unmanaged<NSString>.fromOpaque(sourceFrameRefCon).takeRetainedValue() let string = String(nsString) print(string) } // 其他解码逻辑 }
注意事项
- 如果你无法保证回调100%会被触发,可以改用
takeUnretainedValue()读取对象,在确定指针废弃的时机手动调用Unmanaged<NSString>.fromOpaque(sourceFrameRefCon).release()释放内存 - 所有异步接口的refcon参数都不要直接传栈上局部变量的地址
&xxx,几乎都会触发野指针崩溃
内容的提问来源于stack exchange,提问作者LLooggaann
相关产品推荐
相关产品推荐

