Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios NSURLSession导致EXC\u访问错误_Ios_Swift_Exc Bad Access_Nsurlsession - Fatal编程技术网

Ios NSURLSession导致EXC\u访问错误

Ios NSURLSession导致EXC\u访问错误,ios,swift,exc-bad-access,nsurlsession,Ios,Swift,Exc Bad Access,Nsurlsession,我注意到,实现NSURLSessionDataDelegate并启动任务有时会抛出EXC\u BAD\u访问。给出错误的实际调用方法似乎有所不同,但总是来自CFNetwork。在大多数情况下,调用方法来自NSURLSession delegate\u dataTask:didReceiveData:completionHandler。我在下面附上了两个不同呼叫者的崩溃日志。我还附加了NSURLSessionDataDelegate的实现 不幸的是,我无法可靠地再现错误,因此我没有示例脚本可供共享

我注意到,实现
NSURLSessionDataDelegate
并启动任务有时会抛出EXC\u BAD\u访问。给出错误的实际调用方法似乎有所不同,但总是来自
CFNetwork
。在大多数情况下,调用方法来自
NSURLSession delegate\u dataTask:didReceiveData:completionHandler
。我在下面附上了两个不同呼叫者的崩溃日志。我还附加了
NSURLSessionDataDelegate
的实现

不幸的是,我无法可靠地再现错误,因此我没有示例脚本可供共享。创建和启动
Downloader
对象最终将创建错误。对于较大的文件,这种情况似乎更为常见。我在这里实施了什么错误吗?有没有一个好方法可以从这个stacktrace进行调试

我在iOS10和10.1.1上进行了测试,结果相同

实施:

class Downloader: NSObject, NSURLSessionDataDelegate {
    private let url: String
    var finished = false
    let finishCondition = NSCondition()

    init(url:String) {
        self.url = url
        super.init()
    }

    func start() {
        let config = NSURLSessionConfiguration.defaultSessionConfiguration()
        let session = NSURLSession(configuration: config,
                               delegate: self,
                               delegateQueue: nil)
        guard let u = NSURL(string: url) else {
            return
        }
        let request = NSMutableURLRequest(URL: u)
        let task = session.dataTaskWithRequest(request)
        task.resume()
    }

    func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask,
                    didReceiveData data: NSData) {
    }

    func URLSession(session: NSURLSession,
                    task: NSURLSessionTask,
                    didCompleteWithError error: NSError?) {
        session.invalidateAndCancel()
    }

    func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask,
                    didReceiveResponse response: NSURLResponse,
                                       completionHandler: (NSURLSessionResponseDisposition) -> Void) {
        completionHandler(NSURLSessionResponseDisposition.Allow)
    }

    func waitForFinish() {
        finishCondition.lock()
        while !finished {
            finishCondition.wait()
        }
        finishCondition.unlock()
    }

    func URLSession(session: NSURLSession, didBecomeInvalidWithError error: NSError?) {
        finishCondition.lock()
        finished = true
        finishCondition.broadcast()
        finishCondition.unlock()
    }
}
事故日志#1:

事故日志#2:

更新: 现在,通过在iOS模拟器中运行下面粘贴的循环,我可以半可靠地再现这个错误。这在iOS 9.3上不会发生。如果您运行下面的代码,一分钟内您就会收到错误。由于这很可能发生在模拟器中,与设备相比,我假设这是一个并发问题,随着处理能力/内核的增加,这一问题变得更加可能。 要再现错误,请运行以下命令:

var i = 0
while true {
    print("running: \(i)")
    // random url, larger files seem more likely to cause error
    let url = "http://qthttp.apple.com.edgesuite.net/1010qwoeiuryfg/3340/33409.ts"
    let c = Downloader(url: url)
    c.start()
    c.waitForFinish()
    i += 1
}

试着在僵尸仪器中运行。我的猜测是,在NSURLSession运行时,您的
Downloader
类实例正在被释放,因此当它调用您的didReceiveData方法时,您的对象以前占用的内存包含其他内容。(这就是僵尸。)

在与苹果技术支持人员交谈后,我们确认这是
libBacktraceRecording.dylib
库中的一个bug,该库用于在Xcode中进行调试。我已经提交了一份错误报告,并且被告知它不会在用户设备上崩溃,因为这是一个调试错误,发生在大多数用户设备上不存在的库中。

我无法在僵尸工具中重新创建错误。但是,从“编辑方案”打开“僵尸对象”确实会导致相同的错误,而不会输出任何僵尸对象警告。这两者之间有什么区别吗?我看到了一个类似的崩溃,发生时我确实有僵尸,但它没有捕捉到任何东西。我可以确认这仍然发生在Xcode 9,Sierra 10.12.5的beta 5上。在iOS 10上看到了这一点,但在9.3模拟器上没有看到。同样的症状,同样的回溯,没有任何线索。我在10.0模拟器上看到了类似的崩溃
*thread 64:tid=0x5e3688,0x000000010717deac libBacktraceRecording.dylib`\uu gcd\u queue\u item\u enqueue\u hook\u block\u invoke+4,queue='com.apple.network.connections',stop reason=EXC\u BAD\u ACCESS(code=EXC\uI386\u GPFLT)
我很高兴我不是唯一一个这样的人。有没有一个好的调试方法?你能分享一个链接或者更多关于bug报告的信息吗?那么其他人可以看到它的进展?好奇的是,你到底是如何与苹果的技术支持取得联系的?他们有反应吗?我还没有把它放在openradar上,但苹果公司通常很少给出进度反馈。您可以通过联系Apple获得开发者技术支持。他们通常在下一个工作日回复,反应非常迅速;同样的症状,(NSURLConnectionLoader代码中的EXC_BAD_访问深度,但仅来自Xcode调试会话);任何一个卫兵马洛克,地址消毒剂等都能解决它。相同的动态库用于Mac@user1479585你收到苹果公司关于这个错误的更新了吗?我似乎对Xcode 8.2也有同样的问题。没有更新。在与Apple开发支持人员交谈时,他们说我不应该经常创建新的NSURLSession对象,它们应该是长寿对象。因此,我实现了一个多路复用器,这样多个委托可以在同一个NSURLSession中运行,从而大大减少了错误发生的次数
* thread #12: tid = 0x2521f, 0x000000010010ae8c libBacktraceRecording.dylib`__gcd_queue_item_enqueue_hook_block_invoke, queue = 'com.apple.CFNetwork.Connection', stop reason = EXC_BAD_ACCESS (code=1, address=0xd00f524835000200)
      * frame #0: 0x000000010010ae8c libBacktraceRecording.dylib`__gcd_queue_item_enqueue_hook_block_invoke
        frame #1: 0x000000010010a41c libBacktraceRecording.dylib`gcd_queue_item_enqueue_hook + 232
        frame #2: 0x0000000100759ee8 libdispatch.dylib`_dispatch_introspection_queue_item_enqueue_hook + 40
        frame #3: 0x0000000100738ba4 libdispatch.dylib`_dispatch_queue_push + 196
        frame #4: 0x00000001975ccb3c libnetwork.dylib`nw_connection_read + 448
        frame #5: 0x00000001975d938c libnetwork.dylib`tcp_connection_read + 168
        frame #6: 0x000000018b719d54 CFNetwork`TCPIOConnection::read(unsigned long, unsigned long, void (dispatch_data_s*, CFStreamError) block_pointer) + 172
        frame #7: 0x000000018b782af4 CFNetwork`HTTPEngine::_getBodyIntelligently(void (dispatch_data_s*, CFStreamError, bool) block_pointer) + 816
        frame #8: 0x000000018b780d0c CFNetwork`HTTPEngine::_readBodyStartNextRead() + 76
        frame #9: 0x000000018b783664 CFNetwork`___ZN10HTTPEngine21_getBodyIntelligentlyEU13block_pointerFvP15dispatch_data_s13CFStreamErrorbE_block_invoke.56 + 344
        frame #10: 0x000000018b719f64 CFNetwork`___ZN15TCPIOConnection4readEmmU13block_pointerFvP15dispatch_data_s13CFStreamErrorE_block_invoke + 480
        frame #11: 0x000000010072d25c libdispatch.dylib`_dispatch_call_block_and_release + 24
        frame #12: 0x000000010072d21c libdispatch.dylib`_dispatch_client_callout + 16
        frame #13: 0x000000010073ab54 libdispatch.dylib`_dispatch_queue_serial_drain + 1136
        frame #14: 0x0000000100730ce4 libdispatch.dylib`_dispatch_queue_invoke + 672
        frame #15: 0x000000010073ce6c libdispatch.dylib`_dispatch_root_queue_drain + 584
        frame #16: 0x000000010073cbb8 libdispatch.dylib`_dispatch_worker_thread3 + 140
        frame #17: 0x000000018a01e2b8 libsystem_pthread.dylib`_pthread_wqthread + 1288
        frame #18: 0x000000018a01dda4 libsystem_pthread.dylib`start_wqthread + 4
var i = 0
while true {
    print("running: \(i)")
    // random url, larger files seem more likely to cause error
    let url = "http://qthttp.apple.com.edgesuite.net/1010qwoeiuryfg/3340/33409.ts"
    let c = Downloader(url: url)
    c.start()
    c.waitForFinish()
    i += 1
}