为什么std :: cout输出在发送NULL后完全消失

pol*_*lot 21 c++ gcc

我花了一段时间才弄清楚为什么一些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;
Run Code Online (Sandbox Code Playgroud)

上面代码段的输出将是:

This line shows up just fine
Let's check the value of some_string:     
Run Code Online (Sandbox Code Playgroud)

因此将NULL输入cout将禁用所有输出.为什么?以及如何解决它?

这不会一直发生 - 具有相同代码的同事获得所有预期的输出.如果你想知道为什么我不能阻止使用if语句将NULL输入cout:我在大型代码库中工作,并且不知道这会发生在哪里!我所知道的是我从未出现过的cout陈述.


更多信息:

a_function_that_returns_null()实际上是getenv("HOST").我检查了命令行echo $HOST,因为HOST变量是空的.如果我这样做export HOST=(bash风味),输出就在那里.我不知道HOST变量最初包含什么,也不知道getenv在修改HOST变量之前最初返回的内容; 我所知道的(some_string == 0)都是真的.

Lig*_*ica 28

const char* some_string = a_function_that_returns_null();
Run Code Online (Sandbox Code Playgroud)

你是说它字面上返回一个空指针?

[2003: 27.6.2.5.4]:

template<class traits>
basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>& out, const char* s);
Run Code Online (Sandbox Code Playgroud)

3.要求:s非空.

然后流some_string是未定义的行为; 如果指针无效,你不能取消引用一个指针来获取一个字符串 - 即使是一个空字符串.


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

UB导致不可靠的症状.您并不总是会遇到崩溃可能会有点令人惊讶,因为大多数现代操作系统都会SIGSEGV在您尝试取消引用空指针时始终注意到这一点.

但是,从C++的角度来看,任何事情都可能发生 ; 在您的特定情况下,您的标准库实现可能正在检查空指针并在流上设置错误标志,而不是尝试取消引用指针.这是它的特权.

(这也可能是您后续流操作失败的原因:当设置错误标志时,尝试写入流不会执行任何操作.)

例如,尽管命名s != 0为前置条件,但随GCC 4.6.0一起提供的libstdc ++ 执行此操作:

00325       if (!__s)
00326     __out.setstate(ios_base::badbit);
00327       else
Run Code Online (Sandbox Code Playgroud)

但是,不能依赖此行为 ; 它可以改变在任何时间!


所以,根本就不要这样做.如果你真的必须,请传输一个有效但空的字符串.

有什么问题std::string

  • 很棒的解释! (2认同)

Kei*_*son 8

我很确定这cout << (char*)NULL有不确定的行为.我担心"不要那样做"是我能提供的最佳建议.