Как предотвратить функцию освобождения памяти локальной переменной? - PullRequest
0 голосов
/ 04 июля 2019

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

Я нахожусь в ситуации (не совсем как в приведенном ниже коде), где я должен иметьпеременная-член класса хранит адрес переменной, объявленной в функции.

#include <stdio.h>

static int* p;

void foo(){
    int a = 5;
    p = &a;
}

int main(){
    foo();

    //some delay

    printf("*p = %d\n",*p);
}

В идеале *p должно быть 5, но в конечном итоге это число не 5, и оно сильно отличаетсяраз я перезапустить сценарий.Я считаю, что память, выделенная для a в foo, освобождается автоматически.Как я могу убедиться, что *p равно 5, несмотря на любую задержку?

Ответы [ 4 ]

4 голосов
/ 04 июля 2019

Решение 1 - динамическое выделение памяти с новыми и удаляемыми

Если вы хотите, чтобы ячейка памяти была доступна после выхода из функции, вы должны распределить ее динамически, используя new:

int* foo() {
    int* p = new int(5); // Get pointer to int with value of 5
    return p; 
}

Поскольку этот указатель был выделен с помощью new, он будет стоять до тех пор, пока вы не наберете на нем delete:

int main() {
    int* myPtr = foo(); 

    // Do stuff with myPtr

    delete myPtr; // Free it, now that it's no longer needed.
}

Потенциальные проблемы

Когда люди говорят о необходимости сделатьручное управление памятью в C ++, это обычно то, что они имеют в виду.Выяснить, когда вызывать delete для объекта, может быть сложно, и легко все испортить.

Решение 2 - переменная a существует даже после выхода из функции, и это то же самое a каждый раз, когда функция вызывается

Если мы отмечаем a как статическое, то оноКаждый раз при вызове функции у нее будет один и тот же адрес памяти, и она не будет освобождена:

int* p;
void foo() {
    static int a = 5;

    p = a;
}

int main() {
    foo(); 

    // stuff...

    std::cout << *p << '\n'; // Prints 5, unless you modified *p
}

Но почему?

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

1 голос
/ 04 июля 2019

Если вы хотите, чтобы переменная внутри foo сохранялась после вызова функции, тогда вы должны сделать a статической переменной. C ++ - это стековая машина: это означает, что время жизни переменной ограничено ее областью действия. В вашем примере a ограничен областью действия foo. Если вы сделаете вашу переменную статической, то она продлит время жизни вашей переменной до области верхнего уровня, но ограничит ваш доступ к a в вашей функции.

Я чувствую, что то, что вы пытаетесь сделать, очень вонючий код, но вот что вы просили:

#include <stdio.h>

static int* p;

void foo(){
    static int a = 5; // a will only be initialized to 5 once (see magic statics)
    p = &a;
}

int main(){
    foo();

    //some delay

    printf("*p = %d\n", *p);
}

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

0 голосов
/ 04 июля 2019

Используйте статическую переменную, и она решит вашу проблему 5. С другой стороны, память не будет сохранена из-за того, что это локальная переменная.

0 голосов
/ 04 июля 2019

То, что - это смысл использования автоматических переменных хранения, чтобы исчезнуть, когда они выходят из области видимости.Указывать на них после их уничтожения - неопределенное поведение.UB может вернуть вам правильное значение, неправильное значение, или сбой вашего приложения, или что-то еще.

Если вы хотите сохранить его, не делайте его локальным.Используйте (и возвращайте) unique_ptr / shared_ptr (хотя я все равно не понимаю, почему вы хотите сделать это в своем коде).

Все ответы, предлагающие статическую переменную, плохие.Хотя он будет работать временно, он обязательно создаст множество других проблем, если вы сделаете это привычкой.

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