簡體   English   中英

EXC_BAD_ACCESS(code=2, address=... ) 當排序時目標數組的大小超過特定數字時發生

[英]EXC_BAD_ACCESS(code=2, address= ... ) occurs when the size of target array exceeds particular number while sorting

我試圖比較 3 種算法排序所花費的時間:merge、shell、quick。 對於合並排序,我實現了帶有結構的鏈表用於就地排序——只是切換每個節點的地址,而不是復制和粘貼數據。

但是,當目標數組大小超過特定數字時 - 它大約在 130760~130770 - 遞歸調用合並方法時會拋出 EXC_BAD_ACCESS(code=2, address=...) 錯誤。 大小確實很重要,因為較小的大小不會重現異常。

歸並排序class的代碼如下:

template <typename T>
class MergeSort {
private:
    struct Node {
        T data;
        Node* next;
        Node(T d) : data(d), next(nullptr) {}
    };

    Node* head;
    int size;
    long count = 1;

    void split(Node** head, Node** left, Node** right) {
        Node* fast = *head;
        Node* slow = *head;
        while (fast->next && fast->next->next) {
            fast = fast->next->next;
            slow = slow->next;
        }
        *left = *head;
        *right = slow->next;
        slow->next = nullptr;
    }

    Node* merge(Node* left, Node* right) {
        Node* result = nullptr;
        count++;
        if (!left) return right;
        if (!right) return left;
        if (left->data <= right->data) {
            result = left;
            result->next = merge(left->next, right);
        } else {
            result = right;
            result->next = merge(left, right->next);
        }
        return result;
    }

    void mergeSort(Node** headRef) {
        Node* head = *headRef;
        Node* left = nullptr;
        Node* right = nullptr;
        if (!head || !head->next) return;
        split(&head, &left, &right);
        mergeSort(&left);
        mergeSort(&right);
        *headRef = merge(left, right);
    }


public:
    MergeSort() : head(nullptr), size(0) {}

    void insert(T data) {
        Node* newNode = new Node(data);
        newNode->next = head;
        head = newNode;
        size++;
    }

    void sort() {
        mergeSort(&head);
        std::cout << "Total merge count: " << count << std::endl;
    }

    void override(T arr[]) {
        Node* current = head;
        int i = 0;
        while (current) {
            arr[i++] = current->data;
            current = current->next;
        }
    }
};

異常來自讀取 MergeSort 實例本身的錯誤地址。

在此處輸入圖像描述

在這種情況下,“this”的真實地址是 0x16d4a3448,而試圖讀取的地址是 0x16cca7ff0。

我發現拋出錯誤時,兩個地址的十進制數之差始終為 8369240,這是一個非常有趣的數字。

當指向 null 的節點靠近“right->next”時,問題也總是發生。

我也試過改變數組元素的類型,但它沒有改變數組的臨界大小。 所以堆棧溢出可能不是問題。

似乎由於某種原因,如果數組的大小超過某個固定值,它會讀取錯誤的實例地址,但我不知道為什么這會發生在我身上。

供您參考,我目前正在 M1 macbook air 上使用 Clion 2022.3.1。

我嘗試更改元素的類型並監視 right->next 指向的內容。 這兩者對臨界尺寸的影響不大。

我還在 Clion 中做了另一個項目,它稍微改變了臨界尺寸,但變化不大。

我發現使用lldb的AddressSanitizer對監控memory泄漏有幫助,但我不知道如何使用它。 如果你能給我一些信息,請。 (我對調試工具不友好,因為我不是CS專業,剛入門)

先感謝您。

合並 function 為每個合並的節點調用自身。 這將導致大型列表的堆棧溢出。 將 merge() 更改為迭代。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM