You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 10:30:01