![](/img/trans.png)
[英]EXC_BAD_ACCESS(code=1, address=0x0) occurs when passing a std::map as parameter to a virtual function call
[英]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.