Search code examples
cfor-loopsegmentation-faultqsortkernighan-and-ritchie

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


I currently am beginning at C programming, my long term objective being teaching myself reverse engineering, and I am following the excellent book by Denis M. Ritchie. I chose this book despite it being written in the 90s because of the great care the authors paid to explanations and examples throughout it. Anyway, I was playing with the quicksort algorithm the authors described in section 5.6, and tried to rewrite it by recall, but had trouble because of a segmentation fault that I tried to debug with gdb. The code was :

#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;
}

Long story short, after identifying the line in cause (for (;i>0;i--) printf ("%d\n",*ptrtab[i]);)I put a break on it, and the segmentation fault crashed the program on the first iteration of the for loop, and printf wasn't executed. So I just changed this line in my code to put a while loop instead :

#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;
}

And this code works now. I know there must be quite a few errors throughout my code as I am just a beginner, but I can't grasp the reason why changing from a for to a while loop made a difference... Note that I am using GCC on ubuntu 16.04.

Thank you all for your attention, and sorry for the rambling. Kind regards, S. A.


Solution

  • Your while loop is actually different to the for loop. The while loop decrements i before using it; the for loop does not.