Рассмотрим следующий код:
#include <cstdio>
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ofstream *file1 = new ofstream("file1.txt");
(*file1) << "hi\n";
FILE *file2 = fopen("file2.txt", "w");
fprintf(file2, "hi\n");
abort();
}
file1.txt пуст, но file2.txt содержит текст.
Есть ли способ обеспечить, чтобы все открытые потоки были сброшены после завершения программы, без использования std::endl
или ручных сбросов после каждой записи?
gcc версия 4.1.2 20080704 (Red Hat 4.1.2-54)
Я беру точку зрения Linux или Posix. Если вам требуется только строгое соответствие стандарту языка (например, С++ 11), вам понадобятся конструкторы и деструкторы.
Например, вы можете использовать некоторый интеллектуальный указатель, т. Е. Использовать std :: unique_ptr и объявить:
std::unique_ptr<std::ofstream> file1= new ofstream("file1.txt");
Я настоятельно рекомендую использовать более новую версию GCC, то есть g++
версию 4.9.1. Ваша версия 4.1 очень старая и не соответствует стандарту С++ 11.
С точки зрения Linux, все по-другому, если программа заканчивается сигналом (см. Сигнал (7); обратите внимание, что из обработчиков сигналов можно легально вызывать несколько функций, а exit
невозможен, а некоторые сигналы не могут быть пойманы, а несколько сигналов немедленно прекратить процесс, если не установлен явный обработчик сигналов), через выход (3) или путем возврата из main
(где происходит неявный exit
).
Вы также можете зарегистрироваться с помощью atexit (3) -if, вы не используете умную функцию pointer- для обработки выходных данных, которая бы явно скрывала или закрывала все потоки, которые ваша программа явно хранит где-то (вам нужно будет управлять способами и где). Обратите внимание, что прервать (3) не использовать exit
(или _exit (2) syscall)
Как ответил Константин Владимиров, вы также можете использовать специальные атрибуты функции GCC (например, __attribute__((constructor))
)
exit
. Будет ли glibc вызывать деструктор unique_ptr
при abort
? Мои эксперименты показывают, что этого не будет.
Определенно, никакого законного пути.
Но в gcc 4.1 вы можете взломать __attribute__ ((destructor))
. Это потребует, чтобы сделать поток глобальным и использовать exit (-1)
вместо abort
Вся история выглядит так:
ofstream *file1;
int __attribute__ ((constructor))
pre_exec_fn (void)
{
file1 = new ofstream("file1.txt");
}
int __attribute__ ((destructor))
post_exec_fn (void)
{
file1->flush();
delete file1;
}
int main()
{
(*file1) << "hi\n";
exit(-1);
}
Это решение сильно gcc-специфично и не рекомендуется в обычных случаях, но было несколько раз, для меня было полезно, особенно для отладки, обеспечить, чтобы программа оставила какой-либо журнал.
ofstream file1
иexit()
.exit
не уничтожает объекты с автоматической продолжительностью хранения, что означаетfile1
, но сбрасывает и закрывает C-потоки.printf()
сбрасывается на '\ n', поэтому вы получаете этот текст не потому, что потокиFILE
сбрасываются на abort ()