6 Basic concepts [basic]

6.6 Start and termination [basic.start]

6.6.1 main function [basic.start.main]

Программа должна содержать глобальную функцию с именемmain. Выполнение программы запускает основной поток выполнения ([intro.multithread],[thread.threads]), в которомmain вызывается функция и в котором переменные статической продолжительности хранения могут быть инициализированы ([basic.start.static]) и уничтожены ([basic.start.term]). Это определяется реализацией, требуется ли программа в автономной среде для определенияmain функции. [ Note: В автономной среде запуск и завершение определяются реализацией; start-up содержит выполнение конструкторов для объектов области пространства имен со статической продолжительностью хранения; завершение содержит выполнение деструкторов для объектов со статической продолжительностью хранения. ]end note

Реализация не должна предопределятьmain функцию. Эта функция не должна быть перегружена. Его тип должен иметь связь с языком C ++, и он должен иметь объявленный тип возвращаемого значения int, но в остальном его тип определяется реализацией. Реализация должна позволять как

  • функция() возвратаint и

  • функция(int, указатель на указатель наchar) возвратint

как типmain ([dcl.fct]). В последней форме, с целью демонстрации, вызывается первый параметр функции и вызывается второй параметр функции , где должно быть количество аргументов, переданных программе из среды, в которой программа выполняется. Если не равно нулю эти аргументы должны быть поставлены в счете в качестве указателей на начальные символы с завершающим нулевыми мультибайтными строками ( ntmbs с) ( ) и должны быть указателем на начальный характер ntmbs , который представляет собой имя , используемое для запуска программы или . Значение должно быть неотрицательным. Значение должно быть 0. [ Рекомендуется добавлять любые дополнительные (необязательные) параметры после . ]argc argvargc argc argv[0] argv[argc-1] [multibyte.strings]argv[0] ""argc argv[argc] Note: argvend note

Функциюmain нельзя использовать в программе. Из вне реализации. Программа , которая определяет , как удаленные или что декларирует быть , или плохо сформированным. Функция не должна быть объявлена с . Программа, которая объявляет переменную в глобальной области видимости или объявляет имя с привязкой к языку C (в любом пространстве имен), имеет неправильный формат. Имя не зарезервировано. [ Функции-члены, классы и перечисления могут быть вызваны , как и сущности в других пространствах имен. ]linkage main main main inlinestaticconstexpr main linkage-specificationmain main main Example: mainend example

Завершение программы без выхода из текущего блока (например, путем вызова функции std​::​exit(int)) не уничтожает никаких объектов с автоматической продолжительностью хранения ([class.dtor]). Если std​::​exit вызывается для завершения программы во время уничтожения объекта со статической продолжительностью хранения или продолжительностью хранения потока, программа имеет неопределенное поведение.

Оператор return inmain имеет эффект выхода из основной функции (уничтожение любых объектов с автоматической продолжительностью хранения) и вызоваstd​::​exit с возвращаемым значением в качестве аргумента. Если управление потоками от конца compound-statementизmain, эффект эквивалентенreturn с операндом0 (также см[except.handle]).

6.6.2 Static initialization [basic.start.static]

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

Aconstant initializer для переменной или временного объектаo - это инициализатор, полное выражение которого является константным выражением, за исключением того, что еслиo это объект, такой инициализатор может также вызывать конструкторы constexpr дляo и его подобъектов, даже если эти объекты относятся к нелитеральным типам классов. [ Note: Такой класс может иметь нетривиальный деструктор. ] выполняется, если переменный или временный объект со статической продолжительностью хранения или хранением потока инициализируется константным инициализатором для сущности. Если постоянная инициализация не выполняется, переменная с или есть . Вместе вызываются инициализация нулем и инициализация константой ; все остальные инициализации есть . Всякая статическая инициализация строго происходит до ( ) любой динамической инициализации. [ Динамическая инициализация нелокальных переменных описана в ; локальные статические переменные описаны в . ]end noteConstant initialization static storage duration thread storage duration zero-initializedstatic initializationdynamic initialization[intro.races]Note: [basic.start.dynamic][stmt.dcl]end note

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

  • динамическая версия инициализации не изменяет значение любого другого объекта статического времени или продолжительности хранения потока до его инициализации, и

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

[ Note: Как следствие, если инициализация объектаobj1 относится к объектуobj2 области пространства имен, потенциально требующему динамической инициализации и определенному позже в той же единице преобразования, не указано, будет ли значениеobj2 used значением полностью инициализированногоobj2 (посколькуobj2 было статически инициализирован) или будетobj2 просто нулевым значением. Например,

inline double fd() { return 1.0; }
extern double d1;
double d2 = d1;     // unspecified:
                    // may be statically initialized to 0.0 or
                    // dynamically initialized to 0.0 if d1 is
                    // dynamically initialized, or 1.0 otherwise
double d1 = fd();   // may be initialized statically or dynamically to 1.0

end note]

6.6.3 Dynamic initialization of non-local variables [basic.start.dynamic]

Динамическая инициализация нелокальной переменной со статической продолжительностью хранения неупорядочена, если переменная является неявно или явно созданной специализацией, частично упорядочена, если переменная является встроенной переменной, которая не является неявно или явно конкретизированной специализацией, и в противном случае упорядочена . [ Note: Явно специализированный не встроенный статический член данных или специализация шаблона переменной упорядочили инициализацию. ]end note

Динамическая инициализация нелокальных переменныхV иW со статической продолжительностью хранения упорядочены следующим образом :

  • ЕслиV иW имеют упорядоченную инициализацию иV определены ранееW в одной единице трансляции, инициализацияV выполняется в последовательности перед инициализациейW.

  • ЕслиV имеет частично упорядоченную инициализацию,W не имеет неупорядоченной инициализации иV определен ранееW в каждой единице перевода, в которойW определена, то

    • если программа запускает поток ([intro.multithread]), отличный от основного потока ([basic.start.main]), инициализацияV строго выполняется до инициализацииW;

    • в противном случае инициализацияV выполняется до инициализацииW.

  • В противном случае, если программа запускает поток, отличный от основного, до инициализацииV илиW , то не указано, в каких потоках происходит инициализацияV иW происходит; инициализации не имеют последовательности, если они происходят в одном потоке.

  • В противном случае инициализацииV иW имеют неопределенную последовательность.

[ Note: Это определение позволяет инициализировать последовательность упорядоченных переменных одновременно с другой последовательностью. ]end note

Anon-initialization odr-use - это odr-use ([basic.def.odr]), не вызванная прямо или косвенно инициализацией нелокальной статической переменной или переменной продолжительности хранения потока.

Это определяется реализацией, будет ли динамическая инициализация нелокальной внелинейной переменной со статической продолжительностью хранения последовательно перед первым операторомmain или откладывается. Если это отложено, это обязательно произойдет до любого неинициализационного odr-использования любой не встроенной функции или не встроенной переменной, определенной в той же единице перевода, что и инициализируемая переменная.36 Это определяется реализацией, в каких потоках и в каких точках программы происходит такая отложенная динамическая инициализация. [ Note: Такие точки следует выбирать таким образом, чтобы позволить программисту избежать взаимоблокировок. ] [end noteExample:

// - File 1 -
#include "a.h"
#include "b.h"
B b;
A::A(){
  b.Use();
}

// - File 2 -
#include "a.h"
A a;

// - File 3 -
#include "a.h"
#include "b.h"
extern A a;
extern B b;

int main() {
  a.Use();
  b.Use();
}

Это определяется реализацией ли либоa илиb инициализируется доmain ввода , или задерживаются на инициализацию до тех пор ,a пока первый ODR используемый в main. В частности, еслиa инициализируется до main ввода, не гарантируется, чтоb будет инициализирован до того, как он будет использован odr при инициализацииa, то есть перед вызовомA​::​A . Если, однако,a инициализируется в какой-то момент после первого оператораmain,b будет инициализирован до его использования вA​::​A. ]end example

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

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

Если инициализация нелокальной переменной со статической продолжительностью хранения или продолжительностью хранения потока завершается через исключение,std​::​terminate вызывается.

В этом случае инициализируется нелокальная переменная со статической продолжительностью хранения, имеющая инициализацию с побочными эффектами, даже если она сама не используется odr ([basic.def.odr],[basic.stc.static]).

6.6.4 Termination [basic.start.term]

Destructors для инициализированных объектов (то есть объектов, которыеlifetime были начаты) со статической продолжительностью хранения, и функции, зарегистрированные с помощьюstd​::​atexit, вызываются как часть вызова . Вызов выполняется до вызова деструкторов и зарегистрированных функций. [ Возврат из invokes ( ). ]std​::​exitstd​::​exit Note: main std​::​exit [basic.start.main]end note

Деструкторы для инициализированных объектов с продолжительностью хранения потока в данном потоке вызываются в результате возврата из начальной функции этого потока и в результате вызова этого потокаstd​::​exit. Завершение деструкторов для всех инициализированных объектов с длительностью хранения потока в этом потоке строго происходит до инициирования деструкторов любого объекта со статической продолжительностью хранения.

Если завершение конструктора или динамическая инициализация объекта со статической продолжительностью хранения сильно происходит раньше, чем у другого, завершение деструктора второго упорядочивается до инициирования деструктора первого. Если завершение конструктора или динамическая инициализация объекта с продолжительностью хранения потока происходит раньше, чем у другого, завершение деструктора второго выполняется до запуска деструктора первого. Если объект инициализируется статически, он уничтожается в том же порядке, как если бы объект был инициализирован динамически. Для объекта типа массива или класса все подобъекты этого объекта уничтожаются до того, как будет уничтожен любой объект блочной области со статической продолжительностью хранения, инициализированный во время построения подобъектов. Если уничтожение объекта со статической продолжительностью хранения или продолжительностью хранения потока завершается через исключение, std​::​terminate вызывается.

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

Если завершение инициализации объекта со статической продолжительностью хранения происходит строго перед вызовомstd​::​atexit (см. <cstdlib>,[support.start.term]), Вызов переданной функции std​::​atexit упорядочивается до вызова деструктора для объекта. Если вызовstd​::​atexit строго происходит до завершения инициализации объекта со статической продолжительностью хранения, вызов деструктора для объекта упорядочивается до вызова переданной функцииstd​::​atexit. Если вызовstd​::​atexit строго происходит перед другим вызовомstd​::​atexit, вызов функции, переданной второмуstd​::​atexit вызову, упорядочивается до вызова функции, переданной первомуstd​::​atexit вызову.

Если в обработчиках сигналов ([support.runtime]) не разрешено использование объекта стандартной библиотеки или функции , которая не happen before завершает уничтожение объектов со статической продолжительностью хранения и выполнение std​::​atexit зарегистрированных функций ([support.start.term]), программа имеет неопределенное поведение. [ Note: Если есть использование объекта со статической продолжительностью хранения, которое не происходит до разрушения объекта, программа имеет неопределенное поведение. Завершение каждого потока перед вызовомstd​::​exit или выходом из main него достаточно, но не обязательно, чтобы удовлетворить этим требованиям. Эти требования разрешают диспетчеры потоков как объекты статической продолжительности хранения. ]end note

Вызов функции,std​::​abort() объявленной в, <cstdlib> завершает программу без выполнения каких-либо деструкторов и без вызова функций, переданных вstd​::​atexit() илиstd​::​at_­quick_­exit().