Статические переменные внутри функций в C ++ - размещаются, даже если функция не запускается? - PullRequest
17 голосов
/ 30 мая 2010

Я читал о C ++ в Интернете, и вот одна вещь, на которую я не смог найти ответ.

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

Однако, если функция никогда не вызывается, статическая переменная выделяется?

Спасибо

Ответы [ 7 ]

16 голосов
/ 30 мая 2010

Если функция никогда не вызывается, вероятно, ваш компоновщик deadstrip будет как функцией, так и статической переменной, не позволяя ему вводить сегменты .rodata, .data или .bss ( или эквиваленты формата вашего исполняемого файла).

Однако существуют различные причины, по которым компоновщик может не застрять (флаги, указывающие, что нет, невозможность определить, что зависит от символа и т. Д.).

Стоит проверить файл карты компоновщика (иногда это просто текстовый файл!) Или использовать утилиты objdump, nm или dumpbin в конечном исполняемом файле, чтобы определить, является ли этот символ или связанные с ним символы (например, статические). код инициализатора) выжил.

8 голосов
/ 30 мая 2010

Стандарт C ++, раздел 6.7 гласит:

Инициализация нуля (8.5) всех локальные объекты со статическим хранилищем Продолжительность (3.7.1) выполняется до любая другая инициализация имеет место. Локальный объект типа POD (3.9) с статическая продолжительность хранения инициализирована с константами инициализируется перед первым блоком поступил. Реализация разрешено выполнять рано инициализация других локальных объектов со статической продолжительностью хранения под те же условия, что реализация разрешено статически инициализировать объект со статической продолжительностью хранения в пространстве имен (3.6.2). Иначе такой объект инициализируется первый раз контроль проходит через его заявление; такой объект считается инициализированным на завершение его инициализации.

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

4 голосов
/ 30 мая 2010

Каждый объект в C ++ имеет два вложенных периода времени, связанных с ним: продолжительность хранения и время жизни . Срок хранения - это период, на который выделяется необработанная память, занятая объектом. Время жизни - это период между созданием и разрушением реального объекта в этой памяти. (Для объектов типа POD разрушение конструкции либо не имеет значения, либо неприменимо, поэтому их время жизни соответствует продолжительности их хранения).

Когда кто-то говорит «выделенный», он обычно ссылается на продолжительность хранения . На самом деле язык не указывает точно, когда начинается срок хранения объекта. Достаточно потребовать, чтобы он начался в какой-то момент до того, как начнется время жизни объекта .

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

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


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

void foo() {
  static int *p = new int[100];
}

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

1 голос
/ 30 мая 2010

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

0 голосов
/ 30 мая 2010

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

0 голосов
/ 30 мая 2010

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

0 голосов
/ 30 мая 2010

Да, фактическое распределение зависит от компилятора, хотя я думаю, что каждый компилятор просто резервирует пространство в сегменте .static исполняемого файла (или эквивалент в его формате исполняемого файла). Однако инициализация происходит только в первый раз, когда поток выполнения встречает статический объект, и это требуется стандартом.
Помните, что инициализация глобальных статических объектов работает по-другому. Вы можете получить очень хорошие ответы почти на каждый вопрос на сайте C ++ FAQ Lite . Мне также нравится "Эффективный C ++" Скотта Мейерса.

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