【问题标题】:Segfault in C++ merge sort codeC++ 合并排序代码中的段错误
【发布时间】:2014-02-28 07:33:37
【问题描述】:

试图让它工作.. GDB 似乎表明索引可能由于某种原因而关闭。我正在使用一个名为 Record 的子类的向量,该向量主要包含人口(int)和名称(字符串),需要以两种方式进行排序。 bt 在第 27 行表示空指针,它是 isSmaller() 函数中的“if”语句。此函数与同一程序中的插入排序代码完美配合,但不是合并排序,所以我想知道合并排序代码有什么问题。请指教。算法有问题吗?

bt 返回以下内容:

#0  0x0000000000403160 in CensusData::isSmaller (this=0x7fffffffdd10, type=0,     r1=0x609590, r2=0x0) at CensusDataSorts.cpp:27
#1  0x0000000000403510 in CensusData::mergeIt (this=0x7fffffffdd10, type=0,     list=..., p=0, q=1, r=2) at CensusDataSorts.cpp:96
#2  0x0000000000403347 in CensusData::mergeSortIt (this=0x7fffffffdd10,     type=0, list=..., p=0, r=2) at CensusDataSorts.cpp:70
#3  0x0000000000403645 in CensusData::mergeSort (this=0x7fffffffdd10, type=0)    at CensusDataSorts.cpp:113
#4  0x0000000000401a50 in runMergeSorts (fp=...) at CensusSort.cpp:106
#5  0x0000000000401e6f in main (argc=2, argv=0x7fffffffe068)    at CensusSort.cpp:174

代码出现在下面

bool CensusData::isSmaller(int type, Record* r1, Record* r2)
{
    if(type==POPULATION)
    {
        if(r1->population <= r2->population)
            return true;
    }

    else if(type==NAME)
    {
        if(*(r1->city) <= *(r2->city))
            return true;
    }

    return false;        
}

void CensusData::mergeSortIt(int type, vector<Record*>& list, int p, int r)
{
    if(p < r)
    {
        int q = floor((p+r)/2);
        mergeSortIt(type,list,p,q);
        mergeSortIt(type,list,q+1,r);
        mergeIt(type,list,p,q,r);
    }        
}    

void CensusData::mergeIt(int type, vector<Record*>& list, int p, int q, int r)
{
    int n1=q-p+1;
    int n2=r-q;
    int i,j;

    vector<Record*> L(n1,0);
    vector<Record*> R(n2,0);

    for(i=0; i<n1; i++)
        L[i]=list[p+i];

    for(j=0; j<n2; j++)
        R[j]=list[q+j+1];

    i=0;
    j=0;

    for(int k=p; k<=r; k++)
    {
        if(isSmaller(type,L[i],R[j]))
        {
            list[k]=L[i];
            i++;
        }
        else
        {
            list[k]=R[j];
            j++;
        }
    }
}

void CensusData::mergeSort(int type)
{
    mergeSortIt(type, data, 0, data.size()-1);
}

【问题讨论】:

  • 既然您已经在 GDB 中调试,介意给我们函数调用回溯吗?请指出在显示的代码中发生崩溃的位置。还请添加所涉及的向量的大小以及崩溃发生时的索引。
  • 您的意思是在 GDB 中输入 bt 并发布输出?程序收到信号 SIGSEGV,分段错误。 0x0000000000403160 in CensusData::isSmaller (this=0x7fffffffdd10, type=0, r1=0x609590, r2=0x0) at CensusDataSorts.cpp:27 27 if(r1->population population)
  • 我在需要获取向量大小的地方使用 size() 函数,因为它们是从 csv 文件中填充的。附加了 OP。
  • 是的,bt 命令的输出。请编辑您的问题以包含它。
  • 解决此类问题的最佳方法是使用较小的数据集,然后逐行逐行执行代码,同时观察变量和索引。

标签: c++ sorting merge


【解决方案1】:

问题在于您重写合并记录的方式:

for(int k=p; k<=r; k++)
{
    // Here i or j can be outside L/R bounds
    if(isSmaller(type,L[i],R[j]))
    {
        list[k]=L[i];
        i++;
    }
    else
    {
        list[k]=R[j];
        j++;
    }
}

这里是改写的版本:

int k=p;
for(; k<=r; k++)
{
    if(isSmaller(type,L[i],R[j]))
    {
        list[k]=L[i];
        i++;
        if ( i == L.size() )
          break;
    }
    else
    {
        list[k]=R[j];
        j++;
        if ( j == R.size() )
          break;
    }
}
for ( ; i < L.size(); ++i )
  list[k++]=L[i];
for ( ; j < R.size(); ++j )
  list[k++]=R[j];

我不确定这是否会使您的程序按预期工作,但它应该可以修复您的段错误。

【讨论】:

  • 它给了我一些进步,我在你的新代码中做了一些小的改动......而不是 list[k++] 用于最后 2 个循环,我使用 list[++k] 它现在可以工作了完美无缺!谢谢xD
【解决方案2】:

r2=0x0) 在 CensusDataSorts.cpp:27,即您有一个空指针。

还将比较更改为:

return r1->population < r2->population;

return *(r1->city) < *(r2->city);

否则没有意义。您不能拥有

【讨论】:

  • 第 27 行是上面代码中函数 isSmaller() 的简单 if 条件:if(r1->population population)
  • 是的,要么你需要防止 r2 是空指针,要么你需要正确初始化指针 r2。对不起,上面的简短回答。
  • 完全相同的 isSmaller() 函数与同一程序中的插入排序代码完美配合。所以我想知道合并排序代码有什么问题..
  • 试过了......仍然是同样的问题。问题似乎在于 mergeIt() 中的最后一个 for 循环,如果我评论,代码运行良好(当然没有对数据进行排序)。我可能是错的,因为向量的索引范围可能在所述循环之前关闭。
  • 我同意最可能的原因是排序的向量不健康。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-09
  • 1970-01-01
  • 1970-01-01
  • 2022-01-20
  • 1970-01-01
  • 2016-04-20
  • 2013-10-12
相关资源
最近更新 更多