Swift class 属性 初始化方法后参考点消失

Swift class property reference points disappear after init method

首先,我不是 IOS 开发人员,所以我缺乏知识。 如果这个问题微不足道,我深表歉意,但我对系统的了解还不足以知道如何调试这样的问题,所以感谢您花时间解决我的问题。

我的任务是使用 PJSIP 库为 IOS 编写一个 VoIP 应用程序。

我的模型功能运行良好,我开始将事物分类到它们自己的 classes 中,一切都开始分崩离析。

C 库需要大量引用 variables/pointers。使用我新实例化的 class 如果我将所有内容放入 init() 构造函数中,它就可以工作。但是当我开始将一些部分分开以在同一个 class 中分开方法时,变量似乎改变了参考点。

这是一个用记事本编写的模型,因为我无法提供代码本身,此时我无法访问 Mac:

class Account {
    var accId: c_library_type = 0
    var accCfg: c_library_type2 = c_library_type2()

    init()
    {
        c_config_setting_defaults(&self.accCfg)
        //other code
    }

    public func register()
    {
        c_register_method(&self.accId, &self.accCfg) //Throws "exc_bad_access code=1 address=0x0"
    }   
}

//Somewhere else in the code

var account: Account = Account()
account.register()  

如果我做

class Account {
    var accId: c_library_type = 0
    var accCfg: c_library_type2 = c_library_type2()

    init()
    {
        c_config_setting_defaults(&self.accCfg)
        //other code
        c_register_method(&self.accId, &self.accCfg)
    }   
}

//Somewhere else in the code

var account: Account = Account()

没有问题,c_register_method 按预期工作。

非常感谢有关此问题的任何帮助。

编辑:抛出内存异常的库c文件和方法: https://github.com/chakrit/pjsip/blob/master/pjsip/src/pjsua-lib/pjsua_acc.c#L116 https://github.com/chakrit/pjsip/blob/master/pjsip/src/pjsip/sip_util.c#L435

我看不出使用 & 运算符的原因,因为默认情况下引用类型是按引用传递的,只有在需要使用值类型将其内存地址作为要修改的引用传递时才需要 & 运算符.如果函数不采用 C 中的值类型,我想这应该可以解决问题。

在我们的 C 语言开发人员的帮助下,我们找到了这个问题的原因。

Swift 将变量传递给方法时 - 复制引用的根,但为其子项保留相同的引用,这导致 C 库检查引用值的方式出现问题。当一切都在一个方法中时,这不会发生,因为只有本地引用被传递并且它们没有被复制。

示例:

variable1 :: refId = 0x001
variable1.prop1 :: refId = 0x0011
variable1.prop2 :: refId = 0x0012
variable1.prop3 :: refId = 0x0013

Reference passed to the C library:

(copy) variable1 :: refId = 0x002
variable1.prop1 :: refId = 0x0011
variable1.prop2 :: refId = 0x0012
variable1.prop3 :: refId = 0x0013

库检查数组参考点是否不同于第一个值参考点。如果是这样,它假定数组不为空。

由于复制了主要引用,因此具有不同的引用点,代码假设存在一些实际上不存在的值,由于试图访问不存在的引用,我们得到了 bad_access。

问题已通过更改 register() 方法以接收参数作为 inout 而不是使用 self 来解决。

基于先前模型的示例:

class Account {
    var accId: c_library_type = 0
    var accCfg: c_library_type2 = c_library_type2()

    init()
    {
        c_config_setting_defaults(&self.accCfg)
        //other code
    }

    public func register(id: inout c_library_type, cfg: inout c_library_type2)
    {
        c_register_method(&id, &cfg)
    }   
}

//Somewhere else in the code

var account: Account = Account()
account.register(id: &account.accId, cfg: &account.accCfg)  

感谢您抽出宝贵的时间听取对此问题发表评论的任何人。