【问题标题】:quicksort program with segmentation fault具有分段错误的快速排序程序
【发布时间】:2013-03-14 15:36:10
【问题描述】:

今天我正在学习 R.Sedgewick 的 Algorithms in C 中的快速排序算法。

我对算法的工作原理有了很大的了解。编码部分让我有点困惑,最后我遇到了分段错误。代码如下:

#include <stdio.h>
void quicksort(int[], int, int); // prototype

void quicksort(int a[], int l, int r) // What is the value of l. Why hasn't the author 
                                      // mentioned it. Is it the size of the array? 
{
    int i, j, v, t;
    if(r > l)
    {
        v = a[r];
        i = l - 1; // What is l here? Is it the size if yes look at first while statement
        j = r;

        for(;;)
        {

            /*The algorithm says: scan from right until an element < a[r] is found. Where 
              r is the last position in the array. But while checking in the second while
              loop elements > a[r] is searched */

            while (a[++i] < v); // How can you increment again after reaching end of arrray
                                // size if l is the size of the array
            while (a[--j] > v);
            if(i >= j) break;
            t = a[i]; a[i] = a[j]; a[j] = t;
        }
    }

    t = a[i]; a[i] = a[r]; a[r] = t;

    quicksort(a, l, i - 1);
    quicksort(a, i + 1, r);

    return;
}

int main()
{
    int i, a[10]; // assuming size is 10

    for(i = 0; i < 10; i++)
    {
        scanf("%d", &a[i]);
    }

    int l = 10; // I am passing size of the array
    int r = 9; // position of last element

    quicksort(a, l, r);
    return 0;
}

错误是这样的。假设如果我输入 10 个元素然后按 Enter,会发生以下情况:

1 4 8 2 3 6 4 7 10 9
segmentation fault.

process returned 139(0x8b)

这是调试器返回的:

Breakpoint 1, quicksort (a=0xbffff808, l=0, r=0) at quick.c:11
11      if(r > 1)
(gdb) c
Continuing.

Program received signal SIGSEGV, Segmentation fault.
0x080484fb in quicksort (a=0xbffff808, l=0, r=0) at quick.c:28
28      t = a[i]; a[i] = a[r]; a[r] = t;
(gdb) c
Continuing.

Program terminated with signal SIGSEGV, Segmentation fault.
The program no longer exists.
(gdb) c
The program is not being run.

执行上述程序的正确方法是这样。左右指针什么都没有。如果数组占用 n 个内存位置,则左指针应指向第 0 个位置,右指针应指向 n - 1 个位置。我犯了一个愚蠢的错误,没有在 if 条件中包含快速排序的递归函数。因此,所有的头痛。正确的程序是:

/* Working quicksort
 * Robert sedgewick best
 */

#include <stdio.h>

void quicksort(int[], int, int); // prototype

void quicksort(int a[], int l, int r) 
{
    int i, j, v, t;
    if(r > l)
    {
        v = a[r];
        i = l - 1;
        j = r;

        for(;;)
       {
            while (a[++i] < v); 
            while (a[--j] > v);

            if(i >= j) break;
            t = a[i]; a[i] = a[j]; a[j] = t;

        } // End for here


    t = a[i]; a[i] = a[r]; a[r] = t;

    quicksort(a, l, i - 1);
    quicksort(a, i + 1, r);

    } /* End if here. That is include the recursive
         functions inside the if condition. Then it works 
         just fine. */

    return;
}

int main()
{
    int i, a[5]; // assuming size is 10

    for(i = 0; i < 5; i++)
    {
        scanf("%d", &a[i]);
    }

    int l = 0; // I am passing size of the array
    int r = 4; // position of last element

    quicksort(a, l, r);

       int s;

    for(s = 0; s < 5; s++)
    {
        printf("%d ", a[s]);
    }
    return 0;
}

【问题讨论】:

  • lr 分别代表“左”和“右”。
  • 请粘贴故障信息。当错误就在那里时,你真的不应该让人们通过你的代码挖掘,它应该有助于确定它发生在代码中的位置。如有必要,我也会添加打印输出。
  • 如果数组的元素个数为10,left表示0,r表示9吗?
  • @user2147954:是的,但还有其他问题。例如,如果r == 1,那么t = a[i]... 将中断,因为i 的值是未定义的。
  • 我(可能还有 SO 的 C/C++ 论坛中的大多数其他人)拥有 Sedgewicks 的书籍,而且这个算法并不是他的逐字记录。在它不同的几个地方中,上面已经指出了问题。您可能需要再次检查。

标签: c algorithm quicksort


【解决方案1】:

请在调试器中运行,例如gdb。这将向您显示发生段错误的确切行。如果您在 Google 上搜索“gdb 备忘单”,那么上手将非常容易。记得用-g 标志编译。”

我的会话:

dan@dev1:~ $ gcc -g quick.c
dan@dev1:~ $ gdb a.out
...
(gdb) r
Starting program: /home/dan/a.out 
1 4 8 2 3 6 4 7 10 9

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400572 in quicksort (a=0x7fffffffe530, l=10, r=9) at quick.c:21
21              while (a[++i] < v); // How can you increment again after reaching end of arrray

【讨论】:

  • 断点 1,快速排序 (a=0xbffff808, l=0, r=9) at quick.c:11 11 if(r > 1) (gdb)
  • @user2147954 更新以显示我所做的。您通常不需要逐步查找的段错误。
  • @user2147954 既然您知道是哪一行产生了错误,您应该能够思考是什么原因造成的。
  • 好吧,给我五分钟我会考虑
  • 我确实尝试过,我用 (r > l) 替换了 (r > 1) 但现在我被卡住了,因为 gdb 没有让我知道行号:启动程序:/home/siddarth/Desktop /a.out c 程序收到信号 SIGSEGV,分段错误。快速排序 () (gdb) 中的 0x080484fd c 继续。程序因信号 SIGSEGV、分段错误而终止。该程序已不存在。 (gdb)
【解决方案2】:

lr 分别代表“左”和“右”。

发生分段错误是因为您传递了l = 10,所以while (a[++i] &lt; v); 中断。

[编辑]

while (a[++i] < v);                                
while (a[--j] > v);

这两个循环也有问题:你需要测试ij没有越界。

【讨论】:

  • 好吧假设如果我将 0 传递给 l,即:l = 0 或 l = 1 我仍然会收到分段错误错误
【解决方案3】:
int a[10];
int l = 10;
int r =  9; 

quicksort(a, l, r);

called quicksort(a, l, r)
//l=10,r=9
if(r > 1) // 9 > 1 is true
{
    i = l - 1;//i = 10 - 1 = 9
    for(;;)
    {
        while (a[++i] < v);//a[++i] is a[9+1] = a[10] is out of range!!

【讨论】:

  • 是的,你是对的。这实际上是 (r > l) 是英文字母 l 而不是数字 1。不过感谢您的指出。我也发布了更正的答案
猜你喜欢
  • 2017-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-17
  • 2017-11-04
  • 2016-06-04
  • 1970-01-01
  • 2021-09-05
相关资源
最近更新 更多