简体   繁体   English

为什么std :: cout output在NULL发送给它后完全消失

[英]Why does std::cout output disappear completely after NULL is sent to it

It took me a while to figure out why some cout output seem to disappear into the ether.我花了一段时间才弄清楚为什么一些 cout output 似乎消失在了以太中。 The culprit:罪魁祸首:

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;

The output from the snippet above will be:上面代码段中的 output 将是:

This line shows up just fine
Let's check the value of some_string:     

So feeding a NULL into cout will disable all output afterward.因此,将 NULL 输入 cout 之后将禁用所有 output。 Why?为什么? And how to fix it?以及如何解决?

This doesn't happen all the time - a co-worker with the same code gets all the expected output.这不会一直发生 - 具有相同代码的同事会获得所有预期的 output。 And in case you wonder why I can't just prevent feeding NULL into cout with a if statement: I'm working in a large codebase, and don't know where else this happens.如果你想知道为什么我不能用 if 语句阻止将 NULL 输入 cout:我正在一个大型代码库中工作,不知道还会发生这种情况。 All I know is the cout statements I put never showed up.我所知道的是我提出的 cout 声明从未出现过。


More info:更多信息:

a_function_that_returns_null() is actually getenv("HOST") . a_function_that_returns_null()实际上是getenv("HOST") I checked on the commandline via echo $HOST that the HOST variable is empty.我通过echo $HOST在命令行上检查了 HOST 变量是否为空。 If I do export HOST= (bash flavor), the output are all there.如果我确实export HOST= (bash 风格),那么 output 都在那里。 I have no idea what the HOST variable contains initially nor what getenv returns initially when before I modify the HOST variable;在我修改 HOST 变量之前,我不知道 HOST 变量最初包含什么,也不知道getenv最初返回什么; all I know is (some_string == 0) is true.我所知道的是(some_string == 0)是真的。

const char* some_string = a_function_that_returns_null();

Do you mean that it literally returns a null pointer?你的意思是它真的返回一个 null 指针吗?

[2003: 27.6.2.5.4]:

 template<class traits> basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>& out, const char* s);

3. Requires: s is non-null. 3.要求:s 非空。

Then streaming some_string is Undefined Behaviour;然后流式传输some_string是未定义的行为; you cannot dereference a pointer to get a string — even an empty one — if the pointer is not valid.如果指针无效,则不能取消引用指针来获取字符串——即使是空字符串。


This doesn't happen all the time - a co-worker with the same code gets all the expected output这不会一直发生 - 具有相同代码的同事获得所有预期的 output

UB leads to unreliable symptoms . UB导致不可靠的症状 That you don't always get a crash can be slightly surprising because most modern OSs make a point of always SIGSEGV ing when you try to dereference a null pointer.您并不总是会崩溃可能有点令人惊讶,因为当您尝试取消引用 null 指针时,大多数现代操作系统都会强调始终SIGSEGV ing。

However, from a C++ point of view, anything can happen ;但是,从 C++ 的角度来看,任何事情都可能发生 in your particular case, your standard library implementation may well be checking for a null pointer and setting an error flag on the stream instead of attempting to dereference the pointer.在您的特定情况下,您的标准库实现很可能正在检查 null 指针并在 stream 上设置错误标志,而不是尝试取消引用指针。 That is its prerogative.这是它的特权。

(It's also probably why your subsequent stream operations are failing: attempting to write to a stream does nothing when there's an error flag set.) (这也可能是您随后的 stream 操作失败的原因:尝试写入 stream 在设置错误标志时什么都不做。)

For example, the libstdc++ that ships with GCC 4.6.0, despite naming s != 0 as a precondition , does do this :例如,GCC 4.6.0 附带的 libstdc++,尽管s != 0作为前提条件但确实这样做

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

However, you must not rely on this behaviour ;但是,不能依赖这种行为 it could change at any time !它可能随时改变!


So, simply don't do this.所以,干脆不要这样做。 Stream a valid, but empty, string if you really must. Stream 一个有效但为空的字符串,如果你真的必须的话。

And what's wrong with std::string ? std::string有什么问题?

I'm fairly sure that cout << (char*)NULL has undefined behavior.我相当确定cout << (char*)NULL具有未定义的行为。 I'm afraid that "Don't do that" is the best advice I can offer.恐怕“不要那样做”是我能提供的最好建议。

When you are trying to output const char* , the stream prints all the bytes until it reaches '\0' .当您尝试 output const char*时, stream 会打印所有字节,直到达到'\0' It is leading to undefined behavior.它导致未定义的行为。 For example, you could print some control symbols (ie '\n' , '\r' and so on) and get unpredictable result.例如,您可以打印一些控制符号(即'\n''\r'等)并得到不可预知的结果。

EDIT : Actually streaming of NULL pointer is enough to get UB.编辑:实际上 NULL 指针的流式传输足以获得 UB。 I'm not going to delete my answer due to useful comments.由于有用的评论,我不会删除我的答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM