0

How does one trace calls to std::cout?

The situation I run into every now and then is code (usually some 3rd party code) that will make a call to std::cout and the buffer is not immediately flushed.

Thus the data will is not printed to stdout immediately and shows up later when something else has called std::cout and flushed the buffer via std::endl or std::flush. I am thus left wondering who called std::cout? Now I have to chase it down C++ standard library function call. If the call to std::cout is deeply buried, it can be an annoyance to track down.

What are good ways to trace std::cout or any similar C++ standard library function to see where it is being called? My platform is Linux, though this could apply to any system.

Xofo
  • 1,256
  • 4
  • 18
  • 33
  • 2
    you can try 1) always flush things 2) write your own `cout` 3) set breakpoint to all overload of `operator << (ofstream&,...)` – apple apple Jan 01 '19 at 08:18
  • `git grep "cout"` or `grep -R "cout" .` – Jesper Juhl Jan 01 '19 at 08:20
  • Are You sure it is at Your program level, not operating system? – Robert Andrzejuk Jan 01 '19 at 10:46
  • 1
    Just a bit about terminology: you call **functions**. `std::cout` is not a function; it's an object. You can pass it to functions that you call. So `std::cout.get()` calls the **member function** `get()` on the object `std::cout`. Similarly, `std::cout << "my string";` calls the function `operator<<(basic_stream, const char*)`, passing the object `std::cout` and the address of the literal string. – Pete Becker Jan 01 '19 at 13:46
  • @JesperJuhl - Yes grep is an answer, but when sifting through a lot of code, it would interesting to see other ways. – Xofo Jan 02 '19 at 22:32

1 Answers1

5

The easiest approach is to cause std::cout to always flush:

std::cout << std::unitbuf;

Assuming std::cout is used it will get automatically flushed by all properly written output operations (e.g., all output operations provided by the standard C++ library are properly written).

To actually track these operations down in a debugger the easiest approach is using a non-buffering filtering stream buffer: as there is no buffer this stream buffer’s overflow() method is called for each character which is then easy to intercept in a debugger:

struct trackbuf
    : std::streambuf {
    std::ostream&.   d_out;
    std::streambuf* d_sbuf;
    explicit trackbuf(std::ostream& out)
        : d_out(out), d_sbuf(out.rdbuf(this)) {
    }
    ~trackbuf() { this->d_out.rdbuf(this->d_sbuf); }
    int overflow(int c) override {
        return this->d_sbuf->sputc(c); // set breakpoint here
    }
};

// ...
int main() {
    trackbuf buf(std::cout);
    // ...
}
Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380