【问题标题】:Swift crashes in CFRelease when leaving scope离开范围时 Swift 在 CFRelease 中崩溃
【发布时间】:2015-12-28 06:50:41
【问题描述】:

我刚刚投入到 iOS 开发中,我目前在 queryServer 函数末尾的函数 CFRelease 中遇到运行时错误(我在 get 突出显示的行上添加了注释),但我没有如果我注释掉对 extractIPFromQuery 的函数调用,则会出现错误。

下面的代码获取服务器的名称并将 IP 地址列表返回到该服务器。

func extractIPFromQuery(query: NSArray) -> [String] {
    var addresses = [String]()

    for x in 0...query.count - 1{
        let adr = "\(query[x])"
        let adrStart = adr.startIndex.advancedBy(10)
        let adrEnd = adr.startIndex.advancedBy(18)
        let address = adr.substringWithRange(Range<String.Index>(start: adrStart, end: adrEnd))
        var final = ""

        // Convert the hex version of the address into
        // a human readable version

        for seg in 0...3{
            let start = address.startIndex.advancedBy(seg * 2)
            let end = address.startIndex.advancedBy((seg * 2) + 2)
            let hexRange = Range<String.Index>(start: start, end: end)
            let hexPair = address.substringWithRange(hexRange)

            final += "\(UInt8(strtoul(hexPair, nil, 16)))"
            if(seg != 3){
                final += "."
            }
        }

        addresses.append(final)
    }
    return addresses;
}

func queryServer(hostName: String) -> [String]{
    var ips = [String]()
    if  hostName != "\0" {
        let hostRef = CFHostCreateWithName(kCFAllocatorDefault, hostName).takeRetainedValue()
        while(CFHostStartInfoResolution(hostRef, CFHostInfoType.Addresses, nil) == false){}
        ips += extractIPFromQuery(CFHostGetAddressing(hostRef, nil)!.takeRetainedValue() as NSArray)
    } // Code breaks here
    return ips
}

【问题讨论】:

  • 调用queryServer时是否传递了有效的服务器名称?
  • 代码确实有效,ips 填充了一堆地址
  • 由于离开if 范围时会崩溃,因此这意味着它与范围内使用的变量之一有关:hostRefCFHostGetAddressing 的结果。跨度>
  • 还可以查看stackoverflow.com/questions/25890533/…,了解使用getnameinfo() 将IP 地址转换为字符串的更简单方法。

标签: ios swift


【解决方案1】:

CFHostGetAddressing 的名称中没有“创建”或“复制”, 这意味着它不会返回 (+1) 保留对象。 因此,您必须使用takeUnretainedValue() 来获取 非托管引用的值。

有关这些命名约定的详细信息,请参阅“创建规则”和“获取规则” 在Ownership Policy 在《Core Foundation 的内存管理编程指南》中。

【讨论】:

  • 谢谢你和@Cristik,他们解决了我的问题。
【解决方案2】:

您拥有CFHostGetAddressing 返回的数组的所有权,这意味着ARC 将插入一个release 调用来平衡认为需要平衡的retain 调用,而实际上它不需要去做这个。您应该使用takeUnretainedValue() 而不是takeRetainedValue() 作为CFHostGetAddressing 的名称语义,这并不意味着您需要拥有结果的所有权。

在基本层面上,takeRetainedValue()takeUnretainedValue() 之间的区别在于,前者会在变量 get 超出范围时指示 ARC 插入 release 调用,而后者不会。在语义层面上,前者告诉您想要或需要获得该变量的所有权,这通常意味着对该对象的 retain 调用不平衡,ARC 将对其进行平衡。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多