Подтвердить что ты не робот

Какие операции нужно выполнить перед main()

Я столкнулся с этим вопросом, спрашивая, как выполнить код перед main() в C, отметив, что существуют стратегии для С++. Я в основном жил в прикладном пространстве, поэтому выполнение перед тем, как main() мне никогда не приходило в голову. Какие вещи требуют этой техники?

4b9b3361

Ответ 1

"Какие вещи требуют такой техники?"

Точка факта: нет.

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

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

Например, вы:

  • Не нужно вести список регистраций, которые должны быть явно вызваны. Фактически, вы можете даже объявить и определить весь класс в частной области, вне поля зрения кого-либо, и иметь его доступным для использования при запуске программы.

  • main() не нужно делать кучу дерьма с кучей объектов, о которых это не заботит.

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

Edit:

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

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

Ответ 2

Этот метод может быть использован для инициализации библиотеки или для инициализации данных, которые будут использоваться неявно во время выполнения программы.


GCC предоставляет конструктор и деструктор атрибуты функций, которые вызывают автоматическую вызов функции до того, как выполнение занесено в main() или main() завершено или exit() был вызван, соответственно.

void __attribute__ ((constructor)) my_init(void);
void __attribute__ ((destructor)) my_fini(void);

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

Ответ 3

Вещи, сделанные до основного:

  • На x86 регистр указателя стека обычно равен & = 0XF3, чтобы сделать его кратным 4 (выравнивание)
  • Статические элементы инициализируются
  • нажмите argc и argv (и, если необходимо, окружение)
  • вызов _main = p

g++ 4.4 испускает следующее, прежде чем выйдет какой-либо из моего кода. Технически он вставляет его в начало main перед любым из моего кода, но я видел компиляторы, которые используют _init вместо _main в качестве точки входа:

.cfi_startproc
.cfi_personality 0x3,__gxx_personality_v0
pushq   %rbp
.cfi_def_cfa_offset 16
movq    %rsp, %rbp
.cfi_offset 6, -16
.cfi_def_cfa_register 6
subq    $16, %rsp
movl    %edi, -4(%rbp)
movq    %rsi, -16(%rbp)
# My code follows

Ответ 4

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

Одним из возможных "исключений" является инициализация таблиц глобальных констант во время выполнения. Но это очень плохая практика, поскольку таблицы не разделяются между экземплярами библиотеки/процесса, если вы их заполняете во время выполнения. Гораздо умнее написать script для генерации таблиц static const в качестве исходного файла C или С++ во время сборки.

Ответ 5

Все, что должно запускать код для гарантии инвариантов для вашего кода после запуска main, должно выполняться до main. Такие вещи, как глобальные iostreams, библиотека времени выполнения C, привязки ОС и т.д.

Теперь, действительно ли вам нужно писать код, который делает такие вещи, это то, что все остальные отвечают.

Ответ 6

Если у вас есть библиотека, очень удобно иметь возможность инициализировать некоторые данные, создавать потоки и т.д. перед вызовом main() и знать, что желаемое состояние достигается без отягощения и доверия к клиентскому приложению для явного вызова некоторая инициализация библиотеки и/или код выключения. Поверхностно это может быть достигнуто за счет наличия статического объекта, конструктор и деструктор которого выполняет необходимые операции. К сожалению, несколько статических объектов в разных единицах перевода или библиотеках будут иметь порядок инициализации undefined, поэтому, если они зависят друг от друга (что еще хуже, циклически), они, возможно, еще не достигли своего инициализированного состояния до того, как запрос. Аналогично, один статический объект может создавать потоки и вызывать службы в другом объекте, которые еще не являются потокобезопасными. Таким образом, более строгий подход с правильными экземплярами singleton и блокировками необходим для обеспечения устойчивости перед лицом произвольного использования, и все это выглядит гораздо менее привлекательным, хотя в некоторых случаях это может быть чистая победа.