C ++: становятся ли статические примитивы недействительными при выходе из программы? - PullRequest
4 голосов
/ 20 ноября 2008

Предположим, у меня есть такая функция:

MyClass &MyFunction(void)
{
  static MyClass *ptr = 0;
  if (ptr == 0)
    ptr = new MyClass;
  return MyClass;
}

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

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

EDIT:

Просто чтобы уточнить, я хочу знать, что на самом деле происходит с содержимым статического указателя (или любого другого примитивного типа, такого как int или float), а не с памятью, на которую он указывает. Например, представьте, что ptr указывает на некоторый адрес памяти, который я хочу проверить в деструкторе другого статического класса. Могу ли я рассчитывать на то, что содержимое ptr не изменится (то есть значение указателя не будет очищено в процессе статического уничтожения)?

Спасибо, Джо

Ответы [ 5 ]

6 голосов
/ 20 ноября 2008

При выходе из процесса все выделенные ему страницы памяти будут освобождены ОС (по модулю страниц с общей памятью, которые может использовать кто-то другой).

Однако, как отмечают другие, деструктор для MyClass никогда не вызывается. Также значение, на которое указывает ptr, никогда не менялось. Если у вас есть статическое int со значением 123, то его значение будет оставаться 123 до самого конца времени жизни процесса.

4 голосов
/ 20 ноября 2008

В современных операционных системах вся память приложения выделяется в «куче», специфичной для этого приложения. При выходе из приложения вся память в этой куче будет освобождена.

Итак, память будет освобождена, , но : деструктор для MyClass никогда не будет вызван. Это может быть проблемой, если деструктор отвечает за освобождение любых ресурсов, не связанных с памятью (общий пример - блокировки файловой системы).

3 голосов
/ 20 ноября 2008

Чтобы ответить на ваш вопрос:

'imagine that the ptr points to some memory address which I want to check in the destructor of some other static class'

Ответ - да.
Вы можете увидеть значение указателя (адрес).
Вы можете посмотреть содержимое, если не указали delete по указателю.

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

POD-объекты: на данные можно безопасно ссылаться из деструктора других объектов (даже глобальных).

Другие статические объекты (т. Е. Объекты с деструкторами): в общем случае доступ к этим объектам после выхода из main () небезопасен, поскольку порядок уничтожения неизвестен (это обратный порядок создания. , но порядок создания сложен, см .: Строительный приказ ). Это можно сделать, но вы должны принять явные меры предосторожности, чтобы убедиться, что объект все еще жив.

Примечание: нелокальная статика:

Память всегда будет там, объект будет недействителен после вызова деструктора (обратите внимание, что POD не имеет деструктора).

Примечание: стек:

Действителен только до тех пор, пока не останется область, в которой они объявлены.
После извлечения стека страница памяти, на которой он находится, потенциально может быть отброшена, что приведет к сбоям SEG, если вы попытаетесь получить к нему доступ.

Примечание: куча:

Действителен до тех пор, пока вы не вызовете delete для указателя, который его выделил.
После удаления указателя значение может быть случайным, так как его можно использовать повторно. Потенциально страница, на которой была память, также может быть удалена. Любой доступ к удаленной странице приведет к ошибке SEG.

3 голосов
/ 20 ноября 2008

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

1 голос
/ 20 ноября 2008

Короткий ответ «нет»: ваш указатель не станет «недействительным» во время выхода из программы. То есть значение указателя не будет автоматически сброшено до нуля, и деструктор объекта MyClass, на который он указывает, не будет вызываться автоматически.

Это потому, что указатель является "примитивным типом", то есть не объектом.

Если у вас есть нелокальная (т. Е. Глобальная или статическая) переменная, которая является объектом, то правила будут другими: деструктор объекта будет вызываться, когда программа завершается вызовом exit () или возвратом из основная функция. Он не будет вызван, если программа завершится вызовом abort ().

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