«Программа получила сигнал SIGSEGV, Ошибка сегментации» При попытке получить все ключевые слова 3-символьных комбинаций с помощью рекурсии - PullRequest
0 голосов
/ 30 августа 2018

Я пытаюсь получить все ключевые слова из 3 символов, используя рекурсию, но после некоторых вызовов возможно, стек вызовов заполнен и происходит сбой программы с ошибкой сегментации, Код:

#include <cs50.h>
#include <stdio.h>

void three_Characters(char c, char c2, char c3);

int main(void){
    three_Characters('A', 'A', 'A');
    return 0;
}

void three_Characters(char c, char c2, char c3){

//print 3-characters 
    printf("%c%c%c - ", c, c2, c3);

    /*Recursion termination*/
    if(c == 'z' && c2 == 'z' && c3 == 'z'){
        return;
    }

    /*Avoid symbol characters */
    if(c3 == 'Z'){
        c3 += 6;
        if(c2 == 'Z'){
            c2 += 7;
            if(c == 'Z'){
            c += 7;
            }
        }
    }

    if(c3 == 'z'){
        if(c2 == 'z'){
            c += 1;   c2 = 65;   c3 = 64;
        }else{
            c2 += 1;  c3 = 64;
        }
    }
    three_Characters(c, c2, c3 + 1); 
}

1 Ответ

0 голосов
/ 01 сентября 2018

Как глубоко вы ожидаете, что ваша рекурсия будет выполняться?

Вы получите 52 уровня итерации последнего символа из 'A ... Za ... z', 52 * 52 уровня итерации по последним двум символам и 52 * 52 * 52 общей глубины рекурсии.

Это рекурсия глубиной 140608.

Каждый раз, когда вы вызываете процедуру, вы используете некоторое количество стека. Обратный адрес должен быть сохранен. Часто некоторые регистры также должны быть сохранены.

В 64-битной системе без оптимизации вполне вероятно, что по крайней мере 32 байта стека будут использоваться для каждого уровня рекурсии. Это 4499456 байт. Предел стека в Linux часто составляет 8 МБ, поэтому вам не следует выбегать из стека (и ваша программа не вылетает для меня ни в 64, ни в 32-битном режиме). Но вы будете использовать более половины доступного стека.

Ваша система, вероятно, имеет нижний предел стека (возможно, 4 МБ). Если это так, ваша программа выйдет из стека .

В Linux (и других ОС UNIX), используйте ulimit -s, чтобы узнать, каков текущий предел стека, и ulimit -s unlimited, чтобы удалить предел стека (это также должно позволить вашей программе завершиться без нажатия SIGSEGV).

P.S. Использование рекурсии для этой тривиально повторяемой задачи рекомендуется ill именно потому, что вы будете использовать lot стекового пространства.

...