2016-06-01 20 views
13

Чтобы лучше понять буферизованные потоки в C++, я хотел бы написать простую программу, в которой буфер std::cout НЕ размывается перед завершением. Поскольку я прочитал, что std::cout сбрасывается при нормальном завершении, я попытался сбросить ошибку времени выполнения. Я также избегал использования std::endl, так как я понимаю, что заставляет флеш. Первая попытка:Как создать простую программу на C++, в которой std :: cout не сбрасывается

//file noflush.cpp 
#include <iostream> 

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

Compile с г ++, вызов из терминала:

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

Даже когда я заставляю ошибки во время выполнения, кажется, буфер все еще получает покраснел от завершения. Возможно ли «запрячь» некоторые данные в буфере, оставив его неписанным для устройства?

+0

Просто сказать, что даже при прерывании с 'станд :: прерыванием()' буфер очищается, (с помощью компании Apple LLVM версии 6.0 (лязг-600.0.57) (на основе LLVM 3.5svn) с LLVM libC++), хотя accor ding to [cppreference] (http: //en.cppreference.com/w/cpp/utility/program/abort) это реализация определена * независимо от того, закрыты ли открытые ресурсы, такие как файлы * (при вызове 'std :: abort()'). – Walter

ответ

10

Это не стандарт C++, но в POSIX, вы можете отправить сигнал «kill», чтобы убить текущий процесс. Это остановит выполнение без очистки, например, буферы для промывки.

Редактирование: Я понял, что сигналы являются не только POSIX, но и фактически частью стандартной библиотеки C (и включены в стандартную библиотеку C++).

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

Как насчет указателя нумерации нумерации для индуцирования нулевого указателя Исключение/время выполнения seg faul ? Это может быть хороший кросс-платформенный способ убить процесс. – kevinarpe

+0

@kevinarpe разыменование нулевого указателя имеет неопределенное поведение, поэтому он не гарантированно убивает процесс и не переносится технически ... На практике, однако, * сбой при нулевом указателе разыгрывание * может быть более «поддерживаемым», чем POSIX. Это в основном то же предложение, что и ответ Кадчуна, за исключением того, что UB из разуменования нулевого указателя, вероятно, более согласован, чем UB, от разыменования и удаления неинициализированного указателя. – user2079303

+1

@kevinarpe Сбой при разыменовании нулевого указателя не гарантируется. – Leandros

4

на следующем примере, я могу создать поведение, которое вы хотите с 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; 
} 

Затем выход:

Здравствуйте! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! Здравствуйте ! [...] Здравствуйте ! Ошибка сегментации

Мы можем видеть, чтоне печатается перед ошибкой сегментации.

+0

Uhmm ... этот пример работает даже с 10 вместо 10000 в цикле? –

+1

Когда я попытался с 10, ошибка сегментации была немедленной. Таким образом, да, это также работает, но более беспорядочно. – Caduchon

+0

Исходный код НЕ показывает поведение, которое ищет ОП, потому что сбой программы перед тем, как поставить «STILL ALIVE!» в буфере, в то время как с 10 вместо 10000 он падает, не отображая ничего, в то время как Hello! ARE в буфере: это ожидаемый bahaviour – Guiroux

9

Насколько я могу судить, нет совместимого и чистый способа избежать std::cout к flush() до окончания программы (но, конечно же, вы можете использовать нечистые методы, например, повышение сигнала либо directly или indirectly). Согласно cppreference, фактический тип буфера, контролируемый std::cout, является реализацией, но определяется из std::streambuf, что, по-видимому, не позволяет публичному доступу таким образом, чтобы эмулировать молчащее глотание буфера.

Кроме того, как я отметил в комментариях, даже аварийное завершение программы (через std::terminate() или std::abort() может или не закрывать открытые ресурсы, так это опять определяется реализация.

+0

Правильная цитата: «Глобальные объекты std :: cout [...] управляют выводом в буфер потока определенного для реализации типа [...]» (буфер, а не объект потока, определяется реализацией) –

+0

@ DieterLücking Благодарю. Я внесла поправки в текст. – Walter

0

Если я вас правильно, вы хотите захват или игнорировать вывод в 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"; 
} 
0
#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; 
}