C - Ошибка доступа к памяти после нескольких рекурсивных записей в один указатель

Я играл со многими различными и глупыми формами циклов, когда пришел к идее цикла, который я временно назвал циклом FIF (цикл функции).

Он работает довольно хорошо (это в 10 раз медленнее, чем обычный цикл, но пока что nvm), пока он не сделает ровно 174665 повторений. На 174665-м повторе Cannot access memory at address на * K указатель в строке:void fif(bool (*f)(int *x),int i,int *k){, Он всегда падает в одной и той же точке (одно и то же повторение). Есть идеи почему? Тестирование на Ubuntu 15.10, gcc версия 5.2.1 20151010. Я новичок в C, поэтому, пожалуйста, будьте терпеливы с newbi:). Заранее благодарю за любую помощь

Мой код:

#include <stdio.h>
#include <stdbool.h>

#define REPEATS 1.8E5

#ifdef WIN32

#include <windows.h>
double get_time()
{
    LARGE_INTEGER t, f;
    QueryPerformanceCounter(&t);
    QueryPerformanceFrequency(&f);
    return (double)t.QuadPart/(double)f.QuadPart;
}

#else

#include <sys/time.h>
#include <sys/resource.h>

double get_time()
{
    struct timeval t;
    struct timezone tzp;
    gettimeofday(&t, &tzp);
    return t.tv_sec + t.tv_usec*1e-6;
}

#endif

bool fifFunction(int *k);
void fif(bool (*f)(int *x),int i,int *k);

int main()
{
        //FIF

        printf("FIF loop\n");
        double t = get_time();
        int k = 0;
        fif(fifFunction,REPEATS,&k);
        printf("time: %f\n",get_time() - t);    
    return 0;
}

bool fifFunction(int *k)
{
        return (*k = *k + 1);
}


void fif(bool (*f)(int *x),int i,int *k){
    if (i > 0){
        if ((*f)((k)) == false){
            return;
        }
        fif(f,(i-1),k);
    }
}

1 ответ

Решение

Это потому, что вы уничтожаете стек вызовов.

void fif(bool (*f)(int *x),int i,int *k){
    if (i > 0){
        if ((*f)((k)) == false){
            return;
        }
        fif(f,(i-1),k); // HERE
    }
}

На линии отмечены HERE, вы повторяете и нажимаете переменные x, i, а также k в стек. По прошествии достаточного количества времени у вас заканчивается свободное место, и программа вылетает. Если вы компилируете с -O3, gcc преобразует это в итерацию, так как это хвосто-рекурсивный вызов, но вы абсолютно не должны полагаться на это поведение. Вместо этого вы должны написать это с помощью цикла.

Другие вопросы по тегам