SW方法属性引用点在init方法后消失

时间:2018-05-16 19:03:44

标签: ios c swift pjsip

首先,我不是IOS开发人员,所以我的知识缺乏。 如果这个问题很简单,我很抱歉,但是我不太了解该系统甚至不知道如何调试这样的问题,所以感谢你在我的问题上花费的时间。

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

我的模型功能工作正常,我开始将事情分类到他们自己的课程中,这一切都开始分崩离析。

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

这是用记事本写的一个模型,因为我无法提供代码本身,在这个时候我无法访问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

2 个答案:

答案 0 :(得分:0)

在我们的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()方法以接收参数而不是使用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)  

感谢您抽出时间对评论此问题的任何人。

答案 1 :(得分:-2)

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