在指针数组的 qsort 实现中使用 FOR 循环但不使用 WHILE 时出现分段错误

Segmentation Fault when using FOR loop but not when using WHILE in an implementation of qsort on an array of pointers

我目前正在开始 C 编程,我的长期 objective 正在自学逆向工程,并且我正在阅读 Denis M. Ritchie 的优秀书籍。尽管这本书写于 90 年代,但我还是选择了这本书,因为作者非常注意书中的解释和示例。 不管怎样,我在玩作者在 5.6 节中描述的快速排序算法,并试图通过回忆重写它,但由于我试图用 gdb 调试的分段错误而遇到了麻烦。代码是:

#include <stdio.h>
#define MAX 10000

void sort(int **, int, int);

int main(){
    int tab[MAX]={18,7,43,72,2365,743,234,3215,13,456}, i;
    int *ptrtab[MAX];
    for (i=0; i<MAX && tab[i]>0; i++){
        ptrtab[i]=&tab[i];
    }   
    sort(ptrtab, 0, i-1);
    for (;i>0;i--) printf ("%d\n",*ptrtab[i]);
    return 0;
}

void sort(int **ptrtab,int gauche,int droite){
    int i, dernier;
    void echanger(int **, int, int);
    if (gauche>=droite) return;
    dernier=gauche;
    for (i=gauche+1; i<=droite; i++){
        if (*ptrtab[i]< *ptrtab[gauche])
            echanger(ptrtab, ++dernier, i);
    }
    echanger(ptrtab, gauche, dernier);
    sort(ptrtab,dernier+1,droite);
    sort(ptrtab,gauche, dernier);
}

void echanger(int **ptrtab,int a,int b){
    int *temp=ptrtab[a];
    ptrtab[a]=ptrtab[b];
    ptrtab[b]=temp;
}

长话短说,在确定原因 (for (;i>0;i--) printf ("%d\n",*ptrtab[i]);) 中的行后,我对其进行了中断,分段错误在 for 循环的第一次迭代中使程序崩溃,并且 printf 没有被执行。所以我只是在代码中更改了这一行,改为放置 while 循环:

#include <stdio.h>
#define MAX 10000

void sort(int **, int, int);

int main(){
    int tab[MAX]={18,7,43,72,2365,743,234,3215,13,456}, i;
    int *ptrtab[MAX];
    for (i=0; i<MAX && tab[i]>0; i++){
        ptrtab[i]=&tab[i];
    }   
    sort(ptrtab, 0, i-1);
    while (i>0) printf ("%d\n",*ptrtab[--i]);
    return 0;
}

void sort(int **ptrtab,int gauche,int droite){
    int i, dernier;
    void echanger(int **, int, int);
    if (gauche>=droite) return;
    dernier=gauche;
    for (i=gauche+1; i<=droite; i++){
        if (*ptrtab[i]< *ptrtab[gauche])
            echanger(ptrtab, ++dernier, i);
    }
    echanger(ptrtab, gauche, dernier);
    sort(ptrtab,dernier+1,droite);
    sort(ptrtab,gauche, dernier);
}

void echanger(int **ptrtab,int a,int b){
    int *temp=ptrtab[a];
    ptrtab[a]=ptrtab[b];
    ptrtab[b]=temp;
}

现在这段代码可以使用了。 我知道我的代码中肯定有很多错误,因为我只是一个初学者,但我无法理解为什么从 for 更改为 while 循环会有所不同...... 请注意,我在 ubuntu 16.04.

上使用 GCC

感谢大家的关注,抱歉啰嗦。 亲切的问候, S.A.

您的 while 循环实际上与 for 循环不同。 while 循环递减 i before 使用它; for 循环没有。

在:

for (;i>0;i--) printf ("%d\n",*ptrtab[i]);

循环从前一个循环的最后一个值 i 开始,到达数组末尾(所以 i 将是 MAX),或者索引tab 在零点。

在第一种情况下,ptrtab[MAX] 将被索引,这是无效的,在第二种情况下,将使用 ptrtab 的未初始化条目,作为自动变量,将有一个随机值(指向随机内存位置,这可能是无效的(未定义的行为)。