почему глобальная переменная в рекурсии использует больше памяти, чем локальная переменная? - PullRequest
0 голосов
/ 01 мая 2018

У меня есть 2 версии кода на C.

Версия 1:

#include <unistd.h>
#include <stdio.h>

int globalA = 10000;
int globalB = 0;

int recursion(int *a, int *b)
{
    *a = *a - 1;
    *b += *a;
    if (*a < 1) {
        sleep(30);
        return *b;
    } else {
        return recursion(a, b);
    }
}

int main()
{
    printf("globalA: %i\n", globalA);
    printf("globalB: %i\n", globalB);

    recursion(&globalA, &globalB);

    printf("globalA: %i\n", globalA);
    printf("globalB: %i\n", globalB);
    return 0;
}

И версия 2 - тот же код, но без указателей:

#include <unistd.h>
#include <stdio.h>

int globalA = 10000;
int globalB = 0;

int recursion(int a, int b)
{
    a = a - 1;
    b += a;
    if (a < 1) {
        sleep(30);
        return b;
    } else {
        return recursion(a, b);
    }
}

int main()
{
    printf("globalA: %i\n", globalA);
    printf("globalB: %i\n", globalB);
    recursion(globalA, globalB);
    printf("globalA: %i\n", globalA);
    printf("globalB: %i\n", globalB);
    return 0;
}

Я вызываю консольную команду vmmap для os x, когда код находится в строке 12 - sleep (30);

У меня вопрос, почему vmmap показывает для первой версии эту строку для стека:

                                VIRTUAL RESIDENT    DIRTY  SWAPPED VOLATILE   NONVOL    EMPTY   REGION
REGION TYPE                        SIZE     SIZE     SIZE     SIZE     SIZE     SIZE     SIZE    COUNT (non-coalesced)
===========                     ======= ========    =====  ======= ========   ======    =====  =======
Stack                             8192K     476K     476K       0K       0K       0K       0K        2

и для второй версии это:

Stack                             8192K     316K     316K       0K       0K       0K       0K        2

То есть размер резидента стека для версии 1 больше, чем для версии 2.

Я думал, что в версии 2 каждый вызов рекурсии будет создавать новую копию переменных a и b в каждом новом кадре стека. В результате он будет потреблять больше памяти в стеке при каждом обращении к рекурсии.

И в версии 1 нет необходимости создавать новую копию переменных a и b , потому что они передаются по ссылке, а переменные, заданные по ссылке, являются глобальными, поэтому globalA должен находиться в сегменте памяти .data и globalB в сегменте .bss . В результате в стеке требуется меньше места.

Я не прав? Пожалуйста, объясните мне, где здесь уловка.

P.S. Код был скомпилирован с помощью clang

1 Ответ

0 голосов
/ 01 мая 2018

В случае "глобалов" вам не нужно создавать новые копии переменных globalA и globalB в стеке для каждой рекурсии, но вам do по-прежнему приходится создавать новые копии переменных-указателей a и b в стеке для каждой рекурсии. Вы не говорите, какую операционную систему или ABI вы используете, но я ожидаю, что это та, где sizeof(int *) больше, чем sizeof(int).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...