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

Почему вывод 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).

4b9b3361

Ответ 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. Я не собираюсь удалять свой ответ из-за полезных комментариев.