Когда освободится память, используемая в функции? (Программирование на C) - PullRequest
0 голосов
/ 28 сентября 2011

Ниже приведен код

Код:

#include <stdio.h>

int * num(void);

int main(void)
{
    int * num2;
    num2 =num();
    printf("%d\n" , *num2);

    return 0;
}


int * num(void)
{
    int num = 20;

    return &num;
}

Вопрос:

  1. Как мы знаем, функция num является локальной для своей функции num(), поэтому в этом коде я пытаюсь вернуть адрес переменной num в функции функции, которая ее вызывает, что main().

  2. После этого я просто использую оператор разыменования, чтобы извлечь значение конкретной переменной num и распечатать его в функции main().

  3. Есть одна вещь, которую я запутался. Помню, я читал книгу о javascript, в которой упоминается, что время жизни переменной находится внутри функции, что означает, что после того, как функция завершит выполнение своих инструкций и передаст управление обратно функции, которая ее вызывает, значение каждой переменной в функции будет чистым. out (сборщик мусора). Но почему в этом коде моя main() функция все еще может указывать на значение этого конкретного адреса памяти ??

Ответы [ 3 ]

6 голосов
/ 28 сентября 2011

Причина, по которой вы можете видеть значение переменной, заключается в том, как работает стек.Фактически, когда вы вводите функцию num, указатель (указатель стека) перемещается, чтобы добавить пространство для локального хранилища функции.Когда вы выходите из функции, указатель стека эффективно перемещается назад, что означает, что следующий вызов функции перезапишет хранилище стека, использованное в предыдущем вызове функции.Однако до тех пор, пока оно не будет перезаписано, значение существует в подвешенном состоянии.Это все еще на самом деле в памяти, но может быть перезаписано в любой момент.Существование фактического значения может иметь место, а может и не быть.Вот почему выполнение, как вы делаете выше, известно как неопределенное поведение .

В основном ... не делайте этого.

1 голос
/ 28 сентября 2011

Просто добавлю к тому, что @Goz очень хорошо объяснил. Попробуйте этот код:

#include <stdio.h>

int * num(void);

int fib(int n)
{
    if( 0 == n || 1 == n )
        return n;

    return fib(n-1) + fib(n-2);
}

int main(void)
{
    int * num2;
    num2 =num();
    (void)fib(7);
    printf("%d\n" , *num2);

    return 0;
}


int * num(void)
{
    int num = 20;

    return &num;
}

Очень велика вероятность того, что вы не получите "20" при выводе (также есть вероятность завершения программы) Также, когда вы компилируете, компилятор предупреждает вас об этом «предупреждение: функция возвращает адрес локальной переменной»:)

0 голосов
/ 28 сентября 2011

Возвращать указатель на локальную переменную неправильно. Переменная num освобождается, когда эта функция возвращается и этот адрес памяти свободен для использования средой выполнения C для другого значения. Возвращенный указатель теперь недопустим, потому что он указывает на нераспределенную область памяти и будет вызывать неопределенное поведение, если используется. Неопределенное поведение означает, что оно может или не может делать то, что вы хотите. В некоторых случаях происходит сбой программы, в других случаях она может работать. Почему это работает в этом случае, потому что эта часть памяти все еще будет содержать значение 20. Среда выполнения C не заполняет эту часть памяти нулями после освобождения.

...