Получите gcc, чтобы очистить все открытые потоки после завершения, как потоки C

0

Рассмотрим следующий код:

#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)

  • 1
    Как часть раздела C99 о файлах, Другие пути к завершению программы, такие как вызов функции отмены, не обязательно должны закрывать все файлы должным образом. Ваш пример будет лучше работать с ofstream file1 и exit() . exit не уничтожает объекты с автоматической продолжительностью хранения, что означает file1 , но сбрасывает и закрывает C-потоки.
  • 0
    На самом деле printf() сбрасывается на '\ n', поэтому вы получаете этот текст не потому, что потоки FILE сбрасываются на abort ()
Показать ещё 9 комментариев
Теги:
gcc

2 ответа

1

Я беру точку зрения 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)))

  • 0
    Исчерпывающий ответ! Спасибо (проголосовал). Я не думал об использовании умного указателя здесь. Даже в gcc 4.1 для iostream может быть создана простая оболочка. Но все это (включая мой ответ) будет работать только при использовании exit . Будет ли glibc вызывать деструктор unique_ptr при abort ? Мои эксперименты показывают, что этого не будет.
1

Определенно, никакого законного пути.

Но в 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-специфично и не рекомендуется в обычных случаях, но было несколько раз, для меня было полезно, особенно для отладки, обеспечить, чтобы программа оставила какой-либо журнал.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню