Почему вывод std:: cout полностью исчезает после отправки NULL
Мне потребовалось некоторое время, чтобы понять, почему какой-то выход cout, кажется, исчезает в эфире. Преступник:
std::cout<< "This line shows up just fine" << std::endl;
const char* some_string = a_function_that_returns_null();
if (some_string == 0)
std::cout<< "Let check the value of some_string: " << some_string << std::endl;
std::cout<< "This line and any cout output afterwards will not show up" << std::endl;
Вывод фрагмента выше:
This line shows up just fine
Let check the value of some_string:
Таким образом, подача NULL в cout отключит весь вывод после этого. Зачем? И как это исправить?
Это не всегда происходит - сотрудник с тем же кодом получает весь ожидаемый результат. И в случае, если вы задаетесь вопросом, почему я не могу просто предотвратить подачу NULL в cout с утверждением if: я работаю в большой базе кода и не знаю, где еще это происходит! Все, что я знаю, - это утверждения, которые я не показывал.
Дополнительная информация:
a_function_that_returns_null()
на самом деле getenv("HOST")
. Я проверил в командной строке через echo $HOST
, что переменная HOST пуста. Если я делаю export HOST=
(bash flavor), вывод все там. Я понятия не имею, что содержит переменная HOST, а не то, что getenv
возвращает первоначально, прежде чем изменять переменную HOST; все, что я знаю, это (some_string == 0)
.
Ответы
Ответ 1
const char* some_string = a_function_that_returns_null();
Вы имеете в виду, что он буквально возвращает нулевой указатель?
[2003: 27.6.2.5.4]:
template<class traits>
basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>& out, const char* s);
3. Требуется: s не равно null.
Тогда потоковая передача some_string
Undefined Поведение; вы не можете разыменовать указатель, чтобы получить строку — даже пустой; если указатель недействителен.
Это происходит не всегда - сотрудник с тем же кодом получает все ожидаемые выходные данные
UB приводит к ненадежным симптомам. То, что вы не всегда получаете крах, может быть немного удивителен, потому что большинство современных ОС делают точку всегда SIGSEGV
ing, когда вы пытаетесь разыменовать нулевой указатель.
Однако, с точки зрения С++, все может случиться; в вашем конкретном случае стандартная реализация библиотеки может быть проверкой нулевого указателя и установкой флага ошибки в потоке вместо попытки разыменования указателя. Это его прерогатива.
(Вероятно также, почему ваши последующие операции потока не работают: попытка записи в поток ничего не делает, когда установлен флаг ошибки.)
Например, libstdС++, который поставляется с GCC 4.6.0, несмотря на имя s != 0
как предварительное условие, сделайте это:
00325 if (!__s)
00326 __out.setstate(ios_base::badbit);
00327 else
Однако вы не должны полагаться на это поведение; это может измениться в любое время!
Итак, просто не делайте этого. Поток действительной, но пустой строки, если вы действительно должны.
И что не так с std::string
?
Ответ 2
Я уверен, что cout << (char*)NULL
имеет поведение undefined. Я боюсь, что "Не делай этого" - лучший совет, который я могу предложить.
Ответ 3
Когда вы пытаетесь выполнить вывод const char*
, поток печатает все байты, пока не достигнет '\0'
. Это приводит к поведению undefined. Например, вы можете напечатать некоторые управляющие символы (т.е. '\n'
, '\r'
и т.д.) И получить непредсказуемый результат.
РЕДАКТИРОВАТЬ. На самом деле потокового указателя NULL достаточно, чтобы получить UB. Я не собираюсь удалять свой ответ из-за полезных комментариев.