【问题标题】:Segmentation Fault when using FOR loop but not when using WHILE in an implementation of qsort on an array of pointers使用 FOR 循环时出现分段错误,但在指针数组上的 qsort 实现中使用 WHILE 时不会出现分段错误
【发布时间】:2017-06-01 14:58:39
【问题描述】:

我目前开始学习 C 编程,我的长期目标是自学逆向工程,并且我正在学习 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&gt;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.

【问题讨论】:

  • 本书不教授现代和标准的 C。
  • @Olaf 感谢您的评论。你知道一些电子书或教程吗?
  • 该标准值得阅读。但是在某处有一个关于 SO 的书单。

标签: c for-loop segmentation-fault qsort kernighan-and-ritchie


【解决方案1】:

在:

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

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

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

【讨论】:

  • 可能,但更有可能i 开始于tab[i]&gt;0 不再为TRUE 且ptrtab[i] 未初始化的点。
  • @PaulOgilvie 谢谢你的回答。使用 printf("%d\n",*ptrtab[i-1]) 确实解决了问题!
【解决方案2】:

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

【讨论】:

  • 将哨兵添加到选项卡是一种方法。另一个是避免完全定义MAX(只写tab[] = { ... }),不要打扰ptrtab数组(只要写tab +i你会写ptrtab[i]的任何地方),并使用for( int *start=tab; start &lt; tab + sizeof tab / sizeof *tab; start++)进行迭代
  • @WilliamPursell:哨兵已经实现。第一个循环只运行... &amp;&amp; tab[i]&gt;0
  • @jarmod:没有初始化器的数组中的剩余元素是否隐式初始化为 0?
  • @Gerhardh 是的,我相信你是对的,我的错。全局范围数组显然是归零的,但看起来像初始化器少于数组宽度的自动装置(例如 int arr[10] = {1,2,3})也被跟踪初始化为零。已删除我回答的那部分,谢谢。
  • @jarmod 谢谢你的回答,我选择它是因为你先回答了,而且简洁明了:)
猜你喜欢
  • 2018-02-15
  • 1970-01-01
  • 1970-01-01
  • 2019-02-12
  • 1970-01-01
  • 2018-02-17
  • 2020-12-27
  • 2020-10-04
  • 2022-11-16
相关资源
最近更新 更多