码迷,mamicode.com
首页 > 编程语言 > 详细

一个由快速排序引发的段错误

时间:2015-05-20 17:49:38      阅读:164      评论:0      收藏:0      [点我收藏+]

标签:

  今天在实现一个查找功能的时候,需要用到排序,因为用的是C开发,就把自己之前写的快速排序算法直接拿来用了。代码如下:

 1 static void QuickSort(ElemType *array,int left,int right)
 2 {
 3     if(left > right)
 4     {
 5         return;
 6     }
 7     int i,j;
 8     ElemType temp, base;
 9     base = array[left];
10     i = left;
11     j = right;
12     while(i < j)
13     {
14         //顺序很重要,要先从右边开始找
15         while(array[j] >= base && j > i)
16         {
17             j--;
18         }
19         array[i] = array[j];
20         while(array[i] <= base && i < j)
21         {
22             i++;
23         }
24         array[j] = array[i];
25     }
26     //最终将基准数归位
27     array[i] = base;  
28     QuickSort(array,left,i-1);//继续处理左边的,这里是一个递归的过程
29     QuickSort(array,i+1,right);//继续处理右边的 ,这里是一个递归的过程
30 }

  编译->运行,出现的结果是:Segmentation fault(core dumped)。看到这个报错,我首先想到的是数组越界了,可是不管怎么检查,也没有找到越界的地方。

  实在是找不出错误来,于是我就干脆把快排重新写一遍,编译运行成功了。然后一对比,开始我以为我找到原因了,是在代码的第3行:if(left < right)应为if(left <= right),这的确是一个错误,但是却不是导致段错误的原因。因为,即便是没有‘=’,程序也会运行下去的。也就是说,若出现left == right,则在代码的28行这个新的递归中,是会返回来从而结束掉递归的。

  到底是哪里有问题?我分享了代码的很多处都没有找到原因,但是,我注意到一个细节:当我传入的数组的元素为5的时候,是会出现Segmentation fault(core dumped)错误,但是当我传入的数组元素为12的时候,却顺利运行。以这一点为突破口,我将传入的数组元素设为了5,然后使用了gdb调试。

  传入的原始数组为 83 86 77 15 93,下面是排序的过程:

  1. 第一次递归调用后,数组就已经拍好了:15 77 83 86 93,且此时基准数base的位置i为2,left为0。接着进入下一个递归Quick(array,left,i-1);
  2. 新的递归中left = 0,right = 1,经过13~25行的排序后,基准数base的位置i为0,left还是为0。程序进入下一个递归Quick(array,left,i-1),注意到递归中传入的第三个参数为i-1,而此时i = 0,所以,递归调用传入的第三个参数实际上是负值。在我的计算机中为4294967295,这个值也是新的递归中right的值。

  但是,导致Segmentation fault(core dumped)错误的原因,真的是简单的数组越界吗?我仔细思考了一下觉得有两个原因:

  1. 不断递归导致的入栈过程,最终导致栈溢出;
  2. 数组越界;

  乍一看这里应该是情形2的,因为传入的参数是一个越界值。但是,事实上我使用单步调试的时候,在引用array[4294967295]的时候并没有报错。最终的报错的位置为”Quick(array=0x8048034,left = 100,right=17“,从这一句基本结合上面的越界未报错,基本可以判定应该是栈溢出了。

  但是这样的判断还是错的。我写了下面的测试程序:

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 
 4 static void test(int a);
 5 
 6 int main(void)
 7 {
 8     test(0);
 9     return 0;
10 }
11 
12 static void test(int a)
13 {
14     int b;
15     b = ++a;
16     printf("This is the %dth recursion.\n",b);
17     test(b);
18 }

  实验结果显示,直到174544次递归调用,才出现了栈溢出的现象。而我统计快排序中的递归次数,发现在第三次就出现段错误了,这到底是怎么回事?

  最终修改过后的程序如下:

 1 static void QuickSort(ElemType *array,int left,int right)
 2 {
 3     if(left >= right)
 4     {
 5         return;
 6     }
 7     int i,j;
 8     ElemType temp, base;
 9     base = array[left];
10     i = left;
11     j = right;
12     while(i < j)
13     {
14         //顺序很重要,要先从右边开始找
15         while(array[j] >= base && j > i)
16         {
17             j--;
18         }
19         if(i < j)
20         {
21             array[i++] = array[j];    
22         }
23         
24         while(array[i] <= base && i < j)
25         {
26             i++;
27         }
28          if(i < j)
29         {
30             array[j--] = array[i];
31         }
32     }
33     //最终将基准数归位
34     array[i] = base;
35     if(i == 0)
36     {
37         return;
38     }
39     QuickSort(array,left,i-1);//继续处理左边的,这里是一个递归的过程
40     QuickSort(array,i+1,right);//继续处理右边的 ,这里是一个递归的过程
41 }

  虽然问题解决了,但是我还是不知道确切的出错原因,希望知道答案的大牛能解答一下。

 

一个由快速排序引发的段错误

标签:

原文地址:http://www.cnblogs.com/yves/p/4517556.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!