2017-01-17 24 views
0

В настоящее время я начинаю с программирования на C, моя долгосрочная цель - обучать меня обратной инженерии, и я следую превосходной книге Денис М. Ричи. Я выбрал эту книгу, несмотря на то, что она была написана в 90-х годах из-за большой осторожности, которую авторы уделяли объяснениям и примерам на всем протяжении. Во всяком случае, я играл с алгоритмом быстрой сортировки, описанным авторами в разделе 5.6, и попытался переписать его, вызвав отзыв, но имел проблемы из-за ошибки сегментации, которую я пытался отлаживать с помощью gdb. Код был:Сегментация Неисправность при использовании цикла FOR, но не при использовании WHILE в реализации qsort по массиву указателей

#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]);) я положил перерыв на нем, и ошибка сегментации разбилась программа на первую итерацию для цикла, и printf WASN Выполнено. Так что я просто изменил эту строку в своем коде, чтобы поставить 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 изменило ... Обратите внимание, что я использую GCC на ubuntu 16.04.

Благодарю всех вас за внимание и извините за бессвязное отношение. С уважением, S. A.

+0

Книга не учит современным и стандартным C. – Olaf

+0

@ Олаф благодарит вас за ваш комментарий. Знаете ли вы, что есть электронные книги или учебные пособия? –

+0

Стандарт Хорошо, но есть список книг о SO где-то. – Olaf

ответ

4

Ваш цикл while фактически отличается от цикла for. Цикл while уменьшает i до, используя его; цикл for не работает.

+0

Добавление часового к вкладке - один из подходов. Другой способ - избегать определения «MAX» вообще (просто напишите 'tab [] = {...}'), а не беспокоиться с массивом ptrtab (просто напишите 'tab + i' ev где вы бы написали 'ptrtab [i]'), и итерации с помощью 'for (int * start = tab; start

+0

@WilliamPursell: дозор уже реализован. Первый цикл запускается только до тех пор, пока '... && tab [i]> 0'. – Gerhardh

+1

@jarmod: Не остаются ли элементы в массивах, которые не имеют инициализатора, неявно инициализированного до 0? – Gerhardh

1

В:

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

Цикл начинается с последним значением i из предыдущего цикла, где либо он достигает конец массива (так i будет MAX), или индексы tab в точке где он равен нулю.

В первом случае, ptrtab[MAX] будет индексироваться, который является недействительным, во втором случае будет использоваться неинициализированная ввод ptrtab, который, будучи автоматической переменной, будет иметь случайное значение (указывает на случайное место памяти , который, вероятно, будет недействительным (неопределенное поведение).

+0

Возможно, но более вероятно, что 'i' начинается в точке, где' tab [i]> 0' больше не ИСТИНА и 'ptrtab [i]' is not инициализируется. – Gerhardh

+0

@ Герхард, вы правы. Обновлен мой ответ. –

+0

@PaulOgilvie благодарит вас за ответ. Использование printf ("% d \ n", * ptrtab [i-1]) действительно устранило проблему! –

 Смежные вопросы

  • Нет связанных вопросов^_^