简体   繁体   中英

How to make a simple C++ program in which std::cout is not flushed

In an effort to better understand buffered streams in C++, I would like to write a simple program in which the std::cout buffer is NOT flushed before termination. Since I have read that std::cout is flushed on normal termination, I tried throwing a runtime error. I also avoided using std::endl , as I understand that forces a flush. First attempt:

//file noflush.cpp
#include <iostream>

int main() {
    std::cout << "Don't write me to the console!";
    throw 0;
}

Compile with g++, call from terminal:

$ ./noflush
libc++abi.dylib: terminating with uncaught exception of type int
Don't write me to the console!Abort trap: 6

Even when I force a runtime error, it seems the buffer still gets flushed on termination. Is it possible to "strand" some data in the buffer, leaving it unwritten to the device?

This is not standard c++, but in POSIX, you can send a "kill" signal to kill the running process. This will stop the execution without cleanup such as flushing buffers.

Edit: I realized that signals are not only POSIX but actually part of C standard library (and included in the C++ standard library).

#include <csignal>
// ...
std::cout << "Don't write me to the console!";
std::raise(SIGKILL);

As far as I can tell, there is no standard compliant and clean way to avoid std::cout to flush() before program termination (but, of course, you can use unclean methods, eg raising a signal either directly or indirectly ). According to cppreference , the actual buffer type controlled by std::cout is implementation defined but derived from std::streambuf , which does not appear to allow public access in a way that would emulate silent swallowing of the buffer.

Further, as I noted in a comment, even abnormal program termination (via std::terminate() or std::abort() may or may not close open resources, so this is again implementation defined.

With the following example, I can create the behaviour you want with gcc 4.8.3 :

#include <iostream>
#include <vector>

int main()
{
    std::string str;
    for(unsigned long int i = 0; i < 10000; ++i)
        str += "Hello ! ";
    str += "END";
    std::cout << str;

    std::vector<double>* p;
    p->push_back(1.0);
    delete p;

    std::cout << "STILL ALIVE !" << std::endl;

    return 0;
}

Then, the output is :

Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! [...] Hello ! Segmentation fault

We can see than END is not printed before the segmentation fault.

If I get you right, you want to capture or ignore the output to std::cout :

#include <iostream>
#include <sstream>
int main()
{
    // Capture the output to `std::cout`
    {
        std::cout << "[Capture Output]" << std::endl;
        std::stringstream cpature;
        auto restore = std::cout.rdbuf(cpature.rdbuf());

        std::cout << "... captured output ..." << std::endl;

        std::cout.rdbuf(restore);
        std::cout << "[Enable Output]" << std::endl;

        // Display the cpatured output.
        std::cout << cpature.rdbuf();
    }
    std::cout << std::endl;

    // Even more drasticly: Ignore the output to `std::cout`
    {
        std::cout << "[Ignore Output]" << std::endl;
        auto restore = std::cout.rdbuf(nullptr);

        std::cout << "... ignored output ..." << std::endl;

        std::cout.rdbuf(restore);
        std::cout << "[Enable Output]" << std::endl;
    }

    std::cout << "[End]\n";
}
#include <iostream>
#include <sstream>
#include <vector>
int main()
{
    std::stringstream cpature;
    auto restore = std::cout.rdbuf(cpature.rdbuf());    
    std::cout.rdbuf(restore);
    for(unsigned long int i = 0; i < 10000; ++i)
        std::cout <<"Hello ! "  << std::endl;
    std::cout << "END"  << std::endl;

    std::cout << cpature.rdbuf();
    std::vector<double> *p;
    p->push_back(1.0);
    delete p;
    std::cout << "STILL ALIVE !" << std::endl;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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