c++ EXC_BAD_ACCESS(code=2,address= ...)在排序时目标数组的大小超过特定数字时发生

tjvv9vkg  于 2023-01-10  发布在  其他
关注(0)|答案(1)|浏览(101)

我试图比较3种算法排序所花费的时间:对于合并排序,我使用struct实现了链表,用于就地排序--只切换每个节点的地址,而不复制和粘贴数据。
然而,当目标数组大小超过特定的数字时(大约在130760~130770之间),它会在递归调用merge方法时抛出错误EXC_BAD_ACCESS(代码= 2,地址=...)。大小确实很重要,因为较小的大小不会重现异常。
合并排序类的代码如下:

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示例本身的错误地址。
enter image description here
在本例中,"this"的实际地址为0x16d4a3448,尝试读取的地址为0x16cca7ff0。
我发现在抛出错误时,这两个地址的差总是十进制数8369240,这是一个非常有趣的数字。
当指向null的节点靠近"右-〉下一个"时,也总是出现这个问题。
我也试过改变数组元素的类型,但是没有改变数组的临界大小,所以堆栈溢出可能不是问题所在。
似乎由于某种原因,如果数组的大小超过某个固定值,它会读取错误的示例地址,但我不知道为什么会发生这种情况。
供您参考,我目前正在M1 macbook air上使用Clion 2022.3.1。
我试着改变元素的类型并监视right-〉next指向什么,但这两种方法对临界大小的影响都不大。
我还在Clion做了另一个项目,它稍微改变了临界尺寸,不是很大。
我发现使用lldb的AddressSanitizer对监控内存泄漏有帮助,但是我不知道如何使用它,如果你能给我一些信息的话。(我对调试工具不太友好,因为我不是CS专业的,只是初学者)
先谢谢你。

7gyucuyw

7gyucuyw1#

merge函数为每个合并的节点调用自身。这将导致大型列表的堆栈溢出。请将merge()更改为迭代。

相关问题