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

Swift中使用CFDictionarySetValue导致崩溃问题求助

问题描述

开发基于Swift的macOS应用,使用IOKit获取USB设备信息时,调用CFDictionarySetValue触发崩溃,报错信息:

Thread 1: EXC_BAD_ACCESS (code=1,...)

原代码如下:

var matchingDict: CFMutableDictionary?
var val: NSNumber.IntegerLiteralType
var valRef: CFNumber?

matchingDict = IOServiceMatching(kIOHIDDeviceKey)
if let matchingDict {
    val = 1917
    valRef = CFNumberCreate(kCFAllocatorDefault, CFNumberType.sInt32Type, UnsafeMutableRawPointer?(&val))
    CFDictionarySetValue(matchingDict, UnsafeRawPointer?(kIOHIDVendorIDKey), unsafeBitCast(valRef, to: UnsafeRawPointer.self))
}

尝试过三种写法均存在问题:

  • 第一种写法(有警告,运行时崩溃):

    valRef = CFNumberCreate(kCFAllocatorDefault, .sInt32Type, UnsafeMutableRawPointer?(&val))
    

    警告信息:

    Forming 'UnsafeRawPointer' to a variable of type 'Optional'; this is likely incorrect because 'Optional' may contain an object reference.

  • 第二种写法(编译通过但崩溃):

    CFDictionarySetValue(matchingDict, unsafeBitCast(kIOHIDVendorIDKey, to: UnsafeRawPointer.self), unsafeBitCast(valRef, to: UnsafeRawPointer.self))
    
  • 第三种写法(依旧崩溃):

    CFDictionarySetValue(matchingDict, UnsafeRawPointer?(kIOHIDVendorIDKey), unsafeBitCast(valRef, to: UnsafeRawPointer.self))
    
错误原因与修正

崩溃的核心问题有两点:

  1. CFNumberCreate指针传递错误:你传递了&val的可选指针包装,而CFNumberCreate需要指向数值的非可选原始指针;同时NSNumber.IntegerLiteralType本质是Int,和你指定的sInt32Type类型不匹配,直接导致内存访问异常。
  2. CFDictionary键值类型转换错误:kIOHIDVendorIDKey本身就是CFString类型,无需强制转成UnsafeRawPointer;valRef是合法的CFNumber对象,直接传递即可——unsafeBitCast会破坏CF对象的内存管理规则,引发野指针访问。

修正后的代码

var matchingDict: CFMutableDictionary?
// 用Int32类型匹配CFNumber的sInt32Type
let vendorID: Int32 = 1917
var valRef: CFNumber?

matchingDict = IOServiceMatching(kIOHIDDeviceKey)
if let matchingDict {
    // 传递非可选的指针,直接取vendorID的内存地址
    valRef = CFNumberCreate(kCFAllocatorDefault, .sInt32Type, &vendorID)
    // 直接传入CFString和CFNumber对象,无需unsafeBitCast
    CFDictionarySetValue(matchingDict, kIOHIDVendorIDKey, valRef)
}

更简洁的Swift化写法

利用Core Foundation与Foundation的toll-free bridging特性,完全避免手动管理CF指针的麻烦:

if let matchingDict = IOServiceMatching(kIOHIDDeviceKey) as? NSMutableDictionary {
    let vendorID: Int32 = 1917
    matchingDict[kIOHIDVendorIDKey] = vendorID
}

内容的提问来源于stack exchange,提问作者Karterilla

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 01:50:16