为什么在发送NULL之后,std :: 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's 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's check the value of some_string: 

所以给cout提供一个NULL将会禁用所有的输出。 为什么? 以及如何解决它?

这不会一直发生 – 具有相同代码的同事可以获得所有预期的输出。 而且如果你想知道为什么我不能防止用if语句把NULL喂给cout:我在一个大的代码库中工作,不知道这发生在哪里! 我所知道的是我所说的结论从未出现过。


更多信息:

a_function_that_returns_null()实际上是getenv("HOST") 。 我通过echo $HOST检查了命令行,HOSTvariables是空的。 如果我export HOST= (bash flavor),输出全部在那里。 我不知道最初的HOSTvariables包含什么,也没有什么getenv在我修改HOSTvariables之前返回的; 我所知道的是(some_string == 0)是真的。

 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是非空的。

然后streamsome_string是未定义的行为; 如果指针无效,则无法取消引用指针来获取string – 即使是空string也是如此。


这不会一直发生 – 具有相同代码的同事可以获得所有预期的输出

UB导致不可靠的症状 。 你并不总是会崩溃,这可能会让你感到有些意外,因为当你试图解引用一个空指针的时候,大多数现代操作系统都总是使用SIGSEGV

然而,从C ++的angular度来看, 任何事情都可能发生 。 在你的特殊情况下,你的标准库实现可能正在检查一个空指针并在stream上设置一个错误标志,而不是试图解引用指针。 这是它的特权。

(这也可能是为什么你的后续stream操作失败:当设置了错误标志时,试图写入一个stream什么也不做。

例如,尽pipe命名s != 0作为先决条件 ,但是与GCC 4.6.0一起提供的libstdc ++ 这样做 :

 00325 if (!__s) 00326 __out.setstate(ios_base::badbit); 00327 else 

但是, 不能依赖这种行为 。 它可以在任何时候改变!


所以,根本不要这样做。 如果你真的需要,请input一个有效但空的string。

std::string什么问题?

我很确定cout << (char*)NULL有未定义的行为。 恐怕“不要那样做”是我能提供的最好的build议。

当你试图输出const char* ,stream打印所有的字节,直到到达'\0' 。 这是导致未定义的行为。 例如,你可以打印一些控制符号(即'\n''\r'等),并得到不可预知的结果。

编辑 :其实stream空指针就足以得到UB。 由于有用的评论,我不会删除我的答案。