线程 1:EXC_BAD_ACCESS(代码=2,地址=0x16d0f3ff0)

Thread 1: EXC_BAD_ACCESS (code=2, address=0x16d0f3ff0)

我正在开发一个应用程序(在 XCode 版本 11.2 和 Swift 4.2 中),我在其中填写一个 LinkedList 并在使用它之后,删除组成它的元素产生 Thread 1 error: EXC_BAD_ACCESS (code = 2, address = 0x16d0f3ff0)。即使不使用列表中的项目也会发生错误,只需添加它们并尝试消除它们,错误就已经发生了。我用 iPhone 和 IOS version 11.4.1

做的测试

LinkedList的实现如下:

import Foundation

public class Node<T> {

    var value: T
    var next: Node<T>?
    weak var previous: Node<T>?

    init(value: T) {
        self.value = value
    } // init
} // Node

public class LinkedList<T> {

    private var head: Node<T>?

    private var tail: Node<T>?

    public private(set) var count: Int = 0

    public init() { } // init

    public var isEmpty: Bool {
        return  self.head == nil
    } // isEmpty

    public var first: Node<T>? {
        return  self.head
    } // first

    public var last: Node<T>? {
        return  self.tail
    } // last

    public func nodeAt(index: Int) -> Node<T>? {
        if index >= 0 {
            var node =  self.head
            var i = index
            while node != nil {
                if i == 0 {
                    return node
                } // if

                i -= 1
                node = node!.next
            } // while
        } // if

        return nil
    } // nodeAt

    public func removeAll() {
        self.head = nil
        self.tail = nil

        self.count = 0
    } // removeAll

    public func remove(node: Node<T>?) -> String {
        if isEmpty {
            return String("ERROR: Empty list, nothing to remove.")
        } // if

        guard node != nil else {
           return String("ERROR: Invalid node, nothing to remove.")
        } // guard

        let prev = node?.previous
        let next = node?.next

        if next != nil && prev == nil {
            self.head = next
            next?.previous = nil
        } else if next != nil && prev != nil {
            prev?.next = next
            next?.previous = prev
        } else if next == nil && prev != nil {
             self.tail = prev
            prev?.next = nil
        } // if
        node?.previous = nil
        node?.next = nil

        self.count -= 1
        return String("Successfully removed node: \(node!.value)")
    } // remove

    func enqueue(value: T) {
        let newNode = Node(value: value)

        if let tailNode =  self.tail {
               newNode.previous = tailNode
               tailNode.next = newNode
        } else {
                self.head = newNode
        } // else
        self.tail = newNode
        self.count += 1
    }

    func enqueue_first(value: HexRecord) {
        let newNode = Node(value: value)

        if let headNode = self.head {
            newNode.next = headNode
            headNode.previous = newNode
        } 
        self.head = newNode
        self.count += 1
    }

    func dequeue() -> T? {
        let element =  self.head?.value
        self.head =  self.head?.next
        self.count -= 1

        return element
    }

} // LinkedList

相同的节点是HexRecord类型:

public class HexRecord
{
    private var length: Int = 0
    private var address: Int64 = 0
    private var type: Int32 = 0
    private var data = [UInt8] ()
    private var checksum: UInt8 = 0

    init()
    {

    }

    public func getAddress() -> Int64 {
        return address;
    }

    public func getType() -> Int32 {
        return type;
    }

    public func getData() -> [UInt8] {
        return data;
    }

    public func getLength() -> Int {
        return length;
    }

    public func getChecksum() -> UInt8 {
        return checksum;
    }


    public func setAddress(address: Int64) {
        self.address = address;
    }

    public func setData(data: [UInt8]) {
        self.data = data;
    }

    public func setLength(length: Int) {
        self.length = length;
    }

    public func setType(type: Int32) {
        self.type = type;
    }

    public func setChecksum(checksum: UInt8) {
        self.checksum = checksum;
    }
}

用法如下:

func tratar_registros() {

    var records = LinkedList<HexRecord>();

    ....

    let data_line: HexRecord? = try parseRecord(line: line)  // parseRecord convert String to HexRecord
    if (data_line != nil)
    {
        records.enqueue(value: data_line!)
    }
    ....

    records.removeAll();        //Thread 1: EXC_BAD_ACCESS (code=2, address=0x16d0f3ff0)

} // Thread 1: EXC_BAD_ACCESS (code=2, address=0x16d0f3ff0)     if there is no line records.removeAll();

使用调试器,我发现在将值 nil 分配给 self.head 时发生了错误。就在 self.head 具有正确值之前,它变为 nil 并且在到达下一条指令(在 removeAll 函数内)之前跳过错误

在 Debug Navigator 中,stackTrace 中出现错误的最后 2 个函数:

libobjc.A.dylib`_object_remove_assocations:
    0x180d11eec <+0>:   sub    sp, sp, #0x70             ; =0x70 
->  0x180d11ef0 <+4>:   stp    x26, x25, [sp, #0x20]  //Thread 1 error: EXC_BAD_ACCESS (code = 2, address = 0x16d0f3ff0)
    0x180d11ef4 <+8>:   stp    x24, x23, [sp, #0x30]

libswiftCore.dylib`_swift_release_:
    0x104e18d1c <+180>: bl     0x104e1a37c               ; bool swift::RefCounts<swift::SideTableRefCountBits>::doDecrement<(swift::PerformDeinit)1>(unsigned int)
->  0x104e18d20 <+184>: ldp    x29, x30, [sp], #0x10. //Thread 1 error: EXC_BAD_ACCESS (code = 2, address = 0x16d0f3ff0)
    0x104e18d24 <+188>: ret    

有人知道如何解决吗?

谢谢!

在我的例子中,这个错误发生在我创建循环引用时。

我创建了一个 Column 对象,并在列初始值设定项中计算出要创建的列数。为了计算该列表,getter 初始化了一个列数组。

通过更改 LinkedList 的 removeAll 方法解决了以下问题:

public func removeAll() {
    while head != nil {
        removeTail()
    }
} 


public func removeTail() {
    guard let tail = tail else {return}
    if let prev = tail.previous {
        prev.next = nil
        self.tail = prev
    } else {
        self.head = nil
        self.tail = nil
    }
    count -= 1


    if count < 0 { count = 0}
}