Исключение нулевого указателя генерируется, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:
null
. null
. null
, как если бы это был массив. null
, как если бы это был массив. null
как будто это было значение Throwable. Приложения должны бросать экземпляры этого класса, чтобы указать на другие незаконные использования объекта null
.
Ссылка: http://docs.oracle.com/javase/8/docs/api/java/lang/NullPointerException.html
Время жизни переменных функции static
начинается с первого раза [0], поток программы встречает декларацию и заканчивается при завершении программы. Это означает, что время выполнения должно выполнять некоторую книгу, чтобы уничтожить ее, только если она была построена.
Кроме того, поскольку стандарт говорит о том, что статические объекты деструкторов должны выполняться в обратном порядке завершения их построения [1], а порядок построения может зависеть от конкретного прогона программы, порядок
struct emitter {
string str;
emitter(const string& s) : str(s) { cout << "Created " << str; << endl; }
~emitter() { cout << "Destroyed " << str << endl; }
};
void foo(bool skip_first)
{
if (!skip_first)
static emitter a("in if");
static emitter b("in foo");
}
int main(int argc, char*[])
{
foo(argc != 2);
if (argc == 3)
foo(false);
}
Выход:
C:> sample.exe Создано в foo Разрушено в foo
C:> sample.exe 1 Создано в if Создано в foo Разрушено в foo Разрушено в if
C:> sample.exe 1 2 Создано в foo Создано, если уничтожено, если уничтожено в foo
[0]
Поскольку C ++ 98 [2] не имеет ссылки на несколько потоков, как это будет вести себя в многопоточной среде, является неуказанным и может быть проблематичным, поскольку упоминается Родди .
[1]
Раздел C ++ 983.6.3.1
[basic.start.term]
[2]
В C ++ 11 статики инициализируются безопасным потоком, это также известно как Magic Statics .
Существующие объяснения на самом деле не полны без фактического правила из Стандарта, найденного в 6.7:
Нулевая инициализация всех переменных области блока со статической продолжительностью хранения или хранилищем потоков продолжительность выполняется до любой другой инициализации. Постоянная инициализация объекта области области с статической продолжительностью хранения, если это применимо, выполняется до того, как его блок будет введен первым. Реализации разрешено выполнять раннюю инициализацию других переменных области блока со статическими или потоками хранения потоков при тех же условиях, что реализации разрешено статически инициализировать переменную со статикой или длительностью хранения потоков в пространстве пространства имен. В противном случае такая переменная инициализируется, когда первый контроль проходит через его объявление; такая переменная считается инициализированной после завершения ее инициализации. Если инициализация завершается путем исключения исключения, инициализация не завершена, поэтому она будет снова проверена, когда следующий элемент управления войдет в объявление. Если элемент управления входит в объявление одновременно, а переменная инициализируется, одновременное выполнение должно ждать завершения инициализации. Если управление повторно вводит декларацию рекурсивно, когда переменная инициализируется, поведение не определено.
blockquote>
FWIW, Codegear C ++ Builder не разрушает ожидаемый порядок в соответствии со стандартом.
C:\> sample.exe 1 2
Created in foo
Created in if
Destroyed in foo
Destroyed in if
... это еще одна причина не полагаться на порядок уничтожения!
[basic.start.term]
– Ben Voigt 16 June 2015 в 14:10main
и в результате вызоваstd::exit
I>. Можете ли вы указать мне часть стандарта, где он позволяет динамические библиотеки явно? – Motti 17 April 2017 в 19:41