合并排序代码中的分段错误

Posted

技术标签:

【中文标题】合并排序代码中的分段错误【英文标题】:Segmentation fault in merge sort code 【发布时间】:2018-05-08 14:24:49 【问题描述】:

我已经用 C++ 编写了这个合并排序程序,但在运行代码后出现“分段错误(核心转储)”错误。即使没有编译错误。你能告诉我我在做什么错吗?在数组中输入时,它显示该错误。如果我将其更改为 push_back,则输入很好,但稍后在合并功能中,它会显示相同的错误。

//merging 2 sorted subarrays.
#include <iostream>
#include <vector>
using namespace std;

void merge(vector <int> &a,vector <int> &b,vector <int> &c)

    int i=0,j=0,k=0,bL=b.size(),cL=c.size();
    while(i<bL && j<cL)
    
        if(b[i]<c[j])
        
            a[k]=b[i];
            i++;k++;
        
        else
        
            a[k]=c[j];
            j++;k++;
        
    
    while(i<bL)
    
        a[k]=b[i];
        i++;k++;
    
    while(j<cL)
    
        a[k]=c[j];
        j++;k++;
    
    cout<<"array a inside merge is: "<<endl;
    for(int p=0;p<a.size();p++)
    
        cout<<a[p]<<endl;
    


void mergeSort(vector <int> &a)

    vector <int> l, r;
    int mid;
    if(a.size()<2) return;

    mid = a.size()/2;
    for(int i=0;i<mid;i++)
    
        l[i]=a[i];
    
    for(int i=mid;i<a.size();i++)
    
        r[i-mid]=a[i];
    
    mergeSort(l);
    mergeSort(r);
    merge(a, l, r);

int main()

    int n;
    vector <int> a;
    cin>>n;
    for(int i=0;i<n;i++)
    
        cin>>a[i];
    
    mergeSort(a);
    for(int p=0;p<n;p++)
    
        cout<<a[p]<<endl;
    
    return 0;

【问题讨论】:

您可以随时使用自定义比较器进行std::sort 但是我正在学习归并排序算法 1) "即使没有编译错误。" 如果代码编译 - 并不意味着它运行正确。 2) cin&gt;&gt;a[i]; 是未定义的行为,当a 为空时。 3)“如果我将其更改为 push_back,则输入很好,但稍后在合并函数中,它显示相同的错误”然后,您的合并函数具有某种未定义的行为。您是否尝试过使用调试器单步执行您的代码? 你应该学习调试,这是非常有用的技能:) vectors 如果分配给不存在的元素,则不会自动展开。 【参考方案1】:

无论您使用[] 访问向量中的元素,都可能会遇到段错误。 这段代码,

vector <int> a;

给你一个空向量。

如果a 中还没有任何内容,则请求a[0] 将不起作用。 尝试将 a[0] 设置为一个值也不起作用。 它不存在。 然而。

你在mergeSort使用的时候也有类似的问题

vector <int> l, r;

这些也是空向量。

您可以使用push_back(甚至emplace_back)添加新元素。 或者使用constructor overload 来说明你想要多少元素。 例如,

vector <int> a(10);

给你一个十个整数的向量,所以a[0] 可以读取或写入。 a[11] 不是。

先练习使用向量,然后尝试合并排序。

【讨论】:

但我不是要求 [0],而是我在那个位置接受输入?所以,即使它不起作用?另外, push_back 在合并中不起作用,因为我每次都必须从 0 开始,所以如果我 push ,它不会覆盖。 我会更明确一点 - 你正试图在索引 0 中放置一些东西。但是没有空间。【参考方案2】:

获得分段错误的原因是您访问了不存在的内存位置(更准确地说是未分配)。假设您有一个长度为 3 的向量并且您尝试访问第 4 个位置,您会遇到分段错误。

与@doctorlove 的回答相反,我想说可以使用[]。但是,您需要以下实现(仅针对main() 显示,请在其他功能中使用相同的逻辑实现)。有关详细信息,请参阅std::vector 的文档。

int main()

    size_t n;

    std::cin >> n;
    std::vector <int> a(n);

    for(int i=0;i<n;++i)
    
        std::cin >> a[i];
    

    // mergeSort(a);

    for(int i=0;i<n;++i)
    
        std::cout << a[i] << "\n";
    
    return 0;

希望这会有所帮助。干杯。

【讨论】:

还要注意使用++i 而不是i++。增前和增后事项。 谢谢,但我试过这样做,输入变得正确但同样​​的错误再次出现在某个函数中,我在所有向量声明中都应用了这个。 请记住,一般情况下您可能不会遇到段错误。访问无效内存是未定义的行为 这是您可以通过调试解决的问题。尝试在每个函数中逐步注释和取消注释部分代码。这样你就可以知道你到底在哪里遇到了分段错误。这就是我为main() 所做的。而且我相信我已经给出了足够的答案让您从主要答案中找出完整的解决方案。【参考方案3】:

这是修改后的最终代码:

//merging 2 sorted subarrays.
#include <iostream>
#include <vector>
using namespace std;

void merge(vector <int> &a,vector <int> &b,vector <int> &c)

    int i=0,j=0,k=0,bL=b.size(),cL=c.size();
    while(i<bL && j<cL)
    
      if(b[i]<c[j])
      
        a[k]=b[i];
        i++;k++;
      
      else
      
        a[k]=c[j];
        j++;k++;
      
    
    while(i<bL)
    
      a[k]=b[i];
      i++;k++;
    
    while(j<cL)
    
      a[k]=c[j];
      j++;k++;
    
    cout<<"array a inside merge is: "<<endl;
    for(int p=0;p<a.size();p++)
    
      cout<<a[p]<<endl;
    


void mergeSort(vector <int> &a)

    vector <int> l, r;
    int mid;
    if(a.size()<2) return;

    mid = a.size()/2;
    for(int i=0;i<mid;i++)
    
      l.push_back(a[i]);
    

    //change2
    for(int i=0;i<a.size()-mid;i++)
    
      r.push_back(a[mid+i]);
    
    mergeSort(l);
    mergeSort(r);
    merge(a, l, r);

int main()

    int n;
    cin>>n;

    //change1
    vector <int> a(n);
    for(int i=0;i<n;i++)
    
      cin>>a[i];
    
    mergeSort(a);
    cout<<"Final array is:"<<endl;
    for(int p=0;p<n;p++)
    
      cout<<a[p]<<endl;
    
    return 0;

【讨论】:

预期结果将是合并函数当前正在处理的数组部分。经过无数次迭代,最终会收敛形成有序数组!

以上是关于合并排序代码中的分段错误的主要内容,如果未能解决你的问题,请参考以下文章

使用链表合并排序 C 实现

链表上的合并排序

合并排序python中的反转数

C++ 代码的分段错误(核心转储)

归并排序分段故障 NASM

合并排序算法中的 C++“以 std::out_of_range:vector 类型的未捕获异常终止”错误