【问题标题】:Why do I get a segmentation fault here?为什么我在这里遇到分段错误?
【发布时间】:2020-08-03 12:49:24
【问题描述】:
void LinkedList<T>::mergeSort(Node*& curr) {
    if (curr->next != nullptr) { //Thread 1: EXC_BAD_ACCESS (code=2, address=0x7ffeef3ffff8)
        Node *ptr1 = nullptr;
        Node *ptr2 = curr;
        //splits linked list
        for (int i = 0; i < getLength() / 2; i++) {
            ptr1 = ptr2;
            ptr2 = ptr2->next;
        }
        ptr1->next = nullptr;
        ptr1 = curr;
        //recursive call for sorting
        mergeSort(ptr1); //Thread 1: EXC_BAD_ACCESS (code=2, address=0x7ffeef3ffff8)
        mergeSort(ptr2);
        //merge lists back together
        if (ptr1 == nullptr)
            curr = ptr2
        else if (ptr2 == nullptr)
            curr = ptr1

        Node *reff = ptr1;

        while (reff->next != nullptr) {
            reff = reff->next;
        }
        reff->next = ptr2;
        curr = reff;
    }
}

一切似乎都在工作,期待这个功能。我总是遇到分段错误,我很困惑为什么会发生这种情况。

另外,我正在上大学,所以可能有更有效的方式,但这是我可以做到的方式,无需提前了解课程。

我有一个名为 length 的变量来保存长度。那部分是老师实现的。

所以它给了我这个错误:Thread 1: EXC_BAD_ACCESS (code=2, address=0x7ffeef3ffff8)。如何通过 code=2 和其他数字找出错误的含义?

【问题讨论】:

  • 最好给自己倒杯咖啡,然后用调试器单步调试程序来回答这类问题。直到大学毕业后,我才学会如何正确使用调试器,我真的希望不是这样。如果您不知道如何使用它,请学习使用它!
  • 有几个地方可能会取消引用空指针。 Edit 包含错误详细信息的问题,以及它发生在哪一行?
  • getLength() 如何知道curr 参数的长度?
  • Turbo Debugger 是我在计算机科学期间有空闲时间的唯一原因。
  • 你很可能。还需要返回一些东西见Top-down implementation using lists

标签: c++ c++11 linked-list nodes mergesort


【解决方案1】:
for(int i=0;i<getLength()/2;i++)

我有一个名为 length 的变量来保存长度。那部分是老师实现的。

所以,getLength()LinkedList 的成员函数。当我们进行递归调用时,它总是会告诉我们整个LinkedList 中存储的length。但这不是我们想要的——我们想要我们传入的Nodes 链中的节点数。相反,当我们第一次进行递归调用时,我们尝试将其拆分为与它相同数量的节点已经有(前半部分,后半部分零节点)。由于这没有任何进展,我们最终将通过递归调用来炸毁堆栈。

【讨论】:

    【解决方案2】:

    有可能。很多事情都错了。这显示了如何使用std::list 完成它。我不知道 API 是否已提供,但让我们将其设为单独的函数,以获取列表。

    template<typename T>
    void mergesort( std::list<T>& list ){
    

    只有当我们有多个元素时才有工作要做

        auto const size = list.size();
        if( size > 1) {
    

    然后将列表拆分为两个列表。

            auto mid = list.begin();
            std::advance( mid, size/2 );        
            std::list<T> other;        
            other.splice( other.begin(), list, list.begin(), mid );
    

    现在我们有两个子列表,可以在它们上递归调用mergesort。

        mergesort( list );
        mergesort( other );
    

    然后需要合并部分结果。

        list.merge( other );        
    

    我们完成了。查看工作版本here

    【讨论】: