Освобождается ли память, выделенная для глобальной статической переменной, определенной в cpp, после удаления экземпляра ее класса в C++?

У меня есть класс, методы которого определены в файле example.cpp и классе, определенном в example.h. В файле example.cpp определен статический глобальный указатель. (Мне нужно, чтобы этот указатель был определен как статический глобальный указатель в .cpp, так как он вызывается в подпрограмме службы статических прерываний, работающей на «голом железе».) Мне интересно, когда экземпляр этого класса удаляется, является ли память, выделенная этому статическому глобальному указателю, определенному вне класса (внутри файла cpp как статическая глобальная переменная), также освободилась? Меня беспокоит проблема с утечкой памяти. (пожалуйста, не предлагайте ничего с умным указателем, спасибо)

// example.cpp
#include <example.h>
static example* ptr;
example::example(){ prt = this; }
example::~example(){}

// example.h
class example
{
public:
example();
virtual ~example();
int a;
};

//main.c
void main(void)
{
  while(1){
           example eg1;
           delete &eg1;
           }
  //Has all the memory allocated to eg1 been freed up including the global static variable(a pointer)?
}

Я понимаю, что (int a) внутри объекта определенно освобождается после удаления объекта, но освобождается ли память, выделенная самому глобальному статическому указателю (статический пример * ptr)? (Я предполагаю) Если статическая глобальная переменная не используется всеми экземплярами класса, действительно ли она выделяет память для этой статической глобальной переменной, но не освобождает ее после удаления экземпляра? Не приведет ли это к утечке памяти?

Первый раз закинул сюда вопрос. Заранее извините, если что-то непонятно.


person TyL    schedule 12.03.2015    source источник
comment
Кто не просто использует шаблон проектирования singleton?   -  person Lawrence Aiello    schedule 12.03.2015
comment
new и delete должны использоваться в паре, теперь вы видите, в чем проблема с вашим кодом?   -  person billz    schedule 12.03.2015
comment
Я уверен, вы знаете, что ваше утверждение delete &eg1 опасно ошибочно и совершенно не нужно...   -  person Lightness Races in Orbit    schedule 13.03.2015


Ответы (4)


Прежде всего, если вы запустите опубликованный вами код, вы получите следующее:

malloc: *** error for object 0x7fff560a8830: pointer being freed was not allocated

Это связано с тем, что вы удалили &eg1 без предварительного выделения памяти для него в куче с помощью new.

Во-вторых, деструктор/delete очистит только память, связанную с объектом example. Он не обязан очищать static example* ptr.

Глядя на это с другой стороны, деструкторы и delete предназначены для очистки динамически выделяемых данных, то есть данных, которые находятся в куче, а не только в стеке текущего вызова функции. Напротив, static example* ptr является глобальным, который живет в глобальном сегменте данных, отдельном от кучи и стека.

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

Редактировать ------------------

Как уже отмечали другие, переменные static живут в течение всего времени существования программы, поэтому они не будут удалены до тех пор, пока ваша программа не завершится.

Здесь можно многое почерпнуть! static поначалу может сбивать с толку, но хорошее знание этого имеет большое значение.

person CLL    schedule 12.03.2015

Все, что объявлено как static, живет в течение всего времени существования программы. Он строится до первого возможного использования и уничтожается в не полностью указанный момент при завершении программы (т. е. после возврата main или вызова exit).

Кроме того, уничтожение (не умного) указателя никогда не уничтожает объект, на который указывает указатель. Вы должны явно вызвать delete для указателя, если хотите освободить ресурсы, на которые он указывает. (Или используйте умный указатель. Делайте. Они лучше.)

person rici    schedule 12.03.2015
comment
Спасибо за ответ, но я могу ввести вас в заблуждение. Меня интересует не память указателя, а память, выделенная для хранения самого указателя. Я просто немного изменил код, чтобы сделать его более понятным. - person TyL; 13.03.2015
comment
@TyL: Это было предметом моего первого абзаца. Время жизни чего-либо статического — это время жизни программы по определению. - person rici; 13.03.2015
comment
Вы говорите, что статическая глобальная переменная также используется всеми экземплярами этого класса? (Я думал, что его можно использовать только тогда, когда он определен внутри класса как член, а не вне класса). В противном случае статическая переменная не знала бы, сколько экземпляров этого класса я создам? Как вы думаете, может ли цикл while(1) в моем файле main.c привести к утечке памяти? - person TyL; 13.03.2015
comment
@tyl: существует только одна статическая глобальная переменная. Как вы думаете, почему это будет связано с экземпляром класса? Это просто глобальное определение без внешней связи. - person rici; 13.03.2015
comment
Хорошо. Я вижу сейчас. Огромное спасибо!!!!!!! Я продолжал думать, что он будет создан после создания его экземпляра.... - person TyL; 13.03.2015
comment
Порядок разрушения статики не установлен; это в обратном порядке построения. И это происходит после возвращения main. - person Alan Stokes; 13.03.2015
comment
@AlanStokes: Да, но не указан порядок построения статик в разных единицах трансляции, а следовательно, и порядок их уничтожения. Возможно, не полностью указано было бы точнее. - person rici; 13.03.2015

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

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

Кроме того, вам не нужно вызывать delete в main(), так как eg1 является локальной переменной. Когда main возвращается, автоматически вызывается деструктор eg1.

person Vivek    schedule 12.03.2015
comment
Спасибо. Это действительно полезно. Вы говорите, что статическая глобальная переменная также используется всеми экземплярами этого класса? (Я думал, что его можно использовать только тогда, когда он определен в классе, а не вне класса) - person TyL; 13.03.2015
comment
Статическая глобальная переменная доступна для всех экземпляров класса и будет перезаписываться каждый раз, когда создается новый пример объекта. Даже если эту переменную сделать статической переменной-членом класса, она будет перезаписана таким же образом. Поэтому вместо назначения глобальной переменной в конструкторе класса назначение ее &eg1 в main() гарантирует, что она не будет перезаписана. - person Vivek; 13.03.2015

Нет Объект-указатель static не имеет внутренней ссылки на класс example и, конечно же, внутренней ссылки на объект eg1. Если бы система уничтожила ptr только потому, что eg1 вышла за рамки, язык был бы очень сломан.

person Lightness Races in Orbit    schedule 12.03.2015