Как я могу удалить эту ошибку сегментации в программе C - PullRequest
0 голосов
/ 01 ноября 2011

здесь я хочу решить проблему переполнения стека в этом коде. здесь, в этом коде, я вызываю функцию р рекурсивно 350000 раз, поэтому я получил ошибку сегментации когда я убираю 350000 и ставлю 300000 чем работает нормально здесь ошибка сегментации возникает из-за того, что я вызывал рекурсивный вызов функции p несколько раз или слишком глубоко вызывал рекурсивную функцию.

это не работает, потому что я беру if(i != 350000). его остановка может быть в этом диапазоне от 300000 до 327480. Я тестировал 10 раз

КОД:

#include <stdio.h>

void p(char *, int);

int main() 
{
    char *a = "HI";
    int b = 10;
    p(a, b);
    printf("\nComplete");
    return 0;

}
void p(char *a, int b) 
{
    static long int i = 0;

    if (i != 350000) 
    {
        printf("\n%ld \t at Hi hello", i);
        i++;
        p(a, b);
    } else 
    {
        return;
    }
}

когда я проверяю этот код с помощью инструмента valgrind, чем ошибка отчетности valgraind, как это

==9236== Stack overflow in thread 1: can't grow stack to 0x7fe801ff8
==9236== 
==9236== Process terminating with default action of signal 11 (SIGSEGV)
==9236==  Access not within mapped region at address 0x7FE801FF8
==9236==    at 0x4EA012E: _IO_file_write@@GLIBC_2.2.5 (fileops.c:1276)
==9236==  If you believe this happened as a result of a stack
==9236==  overflow in your program's main thread (unlikely but
==9236==  possible), you can try to increase the size of the
==9236==  main thread stack using the --main-stacksize= flag.
==9236==  The main thread stack size used in this run was 8388608.
==9236== Stack overflow in thread 1: can't grow stack to 0x7fe801ff0
==9236== 
==9236== Process terminating with default action of signal 11 (SIGSEGV)
==9236==  Access not within mapped region at address 0x7FE801FF0
==9236==    at 0x4A2269F: _vgnU_freeres (vg_preloaded.c:58)
==9236==  If you believe this happened as a result of a stack
==9236==  overflow in your program's main thread (unlikely but
==9236==  possible), you can try to increase the size of the
==9236==  main thread stack using the --main-stacksize= flag.
==9236==  The main thread stack size used in this run was 8388608.

Пожалуйста, помогите мне, ребята, я действительно хочу решить эту проблему. и я не могу удалить рекурсивный вызов функции из моего кода.

Ответы [ 3 ]

3 голосов
/ 01 ноября 2011

Стеки не неограниченный ресурс. Рекурсия хорошо подходит для алгоритмов, которые относительно быстро сокращают пространство поиска (двоичная сортировка отсортированного массива, двоичный или многоходовой обход дерева и т. Д.).

Если вы столкнулись с алгоритмом, который требует рекурсии до уровня триста пятьдесят тысяч раз, вам действительно следует пересмотреть вопрос об использовании рекурсивного решения.

Например, что-то вроде:

def addUnsigned (a, b):
    if a == 0:
        return b
    return addUnsigned (a-1, b+1)

не хорошо подходит для рекурсии.

Если вы действительно не можете удалить рекурсию, вам нужно сделать то, что предлагает valgrind, изменить размер стека. Например, редактор связей в моей системе, ld, имеет опцию --stack, которая позволяет вам указать зарезервированный (и, необязательно, зафиксированный) размер стека.

1 голос
/ 01 ноября 2011

В этом конкретном примере, если вы поднимаете уровень оптимизации вашего компилятора на достаточно высокий уровень, он должен выполнить удаление хвостовых вызовов, что решит проблему переполнения стека (например, gcc 4.4.5 делает это при -O2 и выше ).

0 голосов
/ 01 ноября 2011

Если вы все еще хотите управлять им программно, вы можете вызвать свою функцию в потоке и установить размер стека для потока (и дождаться завершения потока).

...