【问题标题】:Segmentation fault (core dumped). Heapsort分段错误(核心转储)。堆排序
【发布时间】:2014-04-29 09:00:04
【问题描述】:

我有这个在 Windows 上运行的堆排序程序,但在 ubuntu 14.04 上出现分段错误。

#include<stdio.h>
#define N 5000
int arr[N];
int size=N-1;
int parent(int i)
{
    return (i-1)/2;
}
 int lchild(int i)
{
     return 2*i+1;
}
int rchild(int i)
{
     return 2*i+2;
}
void maxheapify(int arr[],int i)
{
     int larg,t;
     int l=lchild(i);
     int r=rchild(i);
     if(arr[l]>arr[i] && l<=size)
         larg=l;
     else
         larg=i;
     if(arr[r]>arr[larg] && r<=size)
         larg=r;
         if(larg!=i)
         {
             t=arr[larg];
             arr[larg]=arr[i];
             arr[i]=t;
             maxheapify(arr,larg);
         }  
 }
 void buildmaxh(int arr[])
 {
     int i;
     for(i=N/2-1;i>=0;i--)
     maxheapify(arr,i);
 }
 void heapsort(int arr[])
 {
     int i,t;
     buildmaxh(arr);
     size--;
     for(i=N-1;i>0;i--,size--)
     {
         t=arr[0];
         arr[0]=arr[i];
         arr[i]=t;
         maxheapify(arr,0);
     }
}
int main()
{
     srand(time(NULL));
     int i;
     for( i=0;i<N;i++)
          arr[i]=rand()%101;
     heapsort(arr);
     printf("done\n\n");
     return 0;
 }

错误的来源是什么?如何消除此错误?

我尝试按照here 的说明使用 gdb 调试代码。但是我无法按照答案中的描述编译程序。我使用了命令 gcc myfile.c -ggdb myfile。 另外,使用命令: gcc myfile.c -o myfile 我成功编译了程序,这给了我分段错误。 我究竟做错了什么? 谢谢。

【问题讨论】:

  • 你应该用gcc myfile.c -ggdb -o myfile编译它以添加调试信息。
  • #0 0x0000000000400605 in maxheapify (arr=0x600d00, i=4997) at heap.c:22 #1 0x00000000004006c2 in maxheapify (arr=0x600d00, i=2498) at heap.c:33 #2 0x00000000004006ea in buildmaxh (arr=0x600d00) at heap.c:40 #3 0x000000000040070e in heapsort (arr=0x600d00) at heap.c:45 #4 0x00000000004007ff in main () at heap.c:61
  • l=9995 在第 22 行。但是您有一个大小为 5000 的数组。因此,在第 22 行执行 arr[l]&gt;arr[i] 时,您会遇到段错误。你确定你需要maxHeapify 是递归的。在第 33 行将 i 的值加倍时会出现错误,这会在第 22 行产生问题
  • @arunmoezhi if 循环中的大小检查用于此目的。

标签: c linux gcc runtime-error


【解决方案1】:

当你检查哪个孩子是larg时,maxheapify出现错误:

if (arr[l]>arr[i] && l<=size) ...

你把支票弄错了。当您阅读arr[l] 时,l 可能超出范围,这是一个分段违规。如果您首先像这样检查边界:

if (l<=size  && arr[l]>arr[i]) ...

如果l 越界,则不会发生读取访问。 (请记住,&amp;&amp;|| 运算符会使评估短路:在a &amp;&amp; b 中,如果a 已经是false,则永远不会检查b,因为整个表达式不可能为真。 )

之后的几行检查arr[r]也是如此。

另外,请包括&lt;stdlib.h&gt;&lt;time.h&gt;;它们是您的随机化代码所必需的。

【讨论】:

  • 谢谢,问题解决了。但是这个问题也应该出现在 Windows 上。为什么它可以在 Windows 上运行?我使用代码块在 Windows 上运行程序。
  • @Potato_head:如果您在数组范围之外读取,则无法保证程序会崩溃或给出任何类型的错误消息。 C 标准将其称为“未定义行为”,并允许任何事情发生。程序可能会因错误而停止,它可能会默默地继续并给出错误的答案,或者它甚至可能给出正确的答案。这取决于特定的系统、内存如何映射到进程的地址空间以及该内存的内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-25
  • 2021-06-03
相关资源
最近更新 更多