Статические переменные в функциях в C++ - выделили, даже если функция не работает?

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

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

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

Спасибо

17
задан sbi 30 May 2010 в 19:56
поделиться

7 ответов

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

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

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

16
ответ дан 30 November 2019 в 12:43
поделиться

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

0
ответ дан 30 November 2019 в 12:43
поделиться

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

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

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

8
ответ дан 30 November 2019 в 12:43
поделиться

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

1
ответ дан 30 November 2019 в 12:43
поделиться

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

0
ответ дан 30 November 2019 в 12:43
поделиться

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

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

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

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


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

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

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

4
ответ дан 30 November 2019 в 12:43
поделиться

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

0
ответ дан 30 November 2019 в 12:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: