Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

It took me a while to figure out why some cout output seem to disappear into the ether. 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:

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. 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. 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! All I know is the cout statements I put never showed up.


More info:

a_function_that_returns_null() is actually getenv("HOST"). I checked on the commandline via echo $HOST that the HOST variable is empty. If I do export HOST= (bash flavor), the output are all there. I have no idea what the HOST variable contains initially nor what getenv returns initially when before I modify the HOST variable; all I know is (some_string == 0) is true.

like image 777
polyglot Avatar asked Aug 11 '11 00:08

polyglot


People also ask

Why is std :: cout not working?

There is no std::cout in C. In a windowing system, the std::cout may not be implemented because there are windows and the OS doesn't know which one of your windows to output to. never ever give cout NULL. it will stop to work.

What does std :: cout do in C++?

std::cout is used to output a value (cout = character output) std::cin is used to get an input value (cin = character input)

Is std :: cout slow?

As for why it is so "time consuming", (in other words, slow,) that's because the primary purpose of std::cout (and ultimately the operating system's standard output stream) is versatility, not performance.


2 Answers

const char* some_string = a_function_that_returns_null(); 

Do you mean that it literally returns a null pointer?

[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.

Then streaming some_string is Undefined Behaviour; 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

UB leads to unreliable symptoms. That you don't always get a crash can be slightly surprising because most modern OSs make a point of always SIGSEGVing when you try to dereference a null pointer.

However, from a C++ point of view, anything can happen; 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. 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.)

For example, the libstdc++ that ships with GCC 4.6.0, despite naming s != 0 as a precondition, does do this:

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.

And what's wrong with std::string?

like image 109
Lightness Races in Orbit Avatar answered Oct 26 '22 15:10

Lightness Races in Orbit


I'm fairly sure that cout << (char*)NULL has undefined behavior. I'm afraid that "Don't do that" is the best advice I can offer.

like image 24
Keith Thompson Avatar answered Oct 26 '22 15:10

Keith Thompson