Поведение C++ ofstream в случае сбоя программы
Я пытаюсь отладить ошибку времени выполнения, из-за которой моя программа зависает в середине выполнения. Я создал систему ведения журнала, которая записывает простой текстовый файл журнала в процессе выполнения.
Я записываю информацию в файл журнала, просто используя оператор вставки потока (<<) объекта ofstream с сообщениями типа std:: string.
void foo(){
// ... Code block 1 ...
// myLogger.Write (timestamp, "Code block1 successfully executed");
// ... Code block 2 ... PROGRAM FREEZE AND CRASH!
}
У меня такой вопрос: предположим, что моя программа зависает, и мне нужно убить ее процесс из диспетчера задач. Могу ли я доверять своей системе ведения журналов, чтобы она надежно написала все сообщения до момента сбоя?
Или, ссылаясь на вышеупомянутый код, если Code block2 вызывает зависание моей программы, могу ли я верить, что сообщение "Code block1 успешно выполнено" в любом случае действительно будет отображаться в моем файле журнала?
PS Я работаю в Windows, и причина, по которой я обеспокоен, заключается в том, что я не полностью доверяю поведению ОС в отношении разрешений на доступ к файлам в нечетных случаях. Моя программа имеет разрешение на чтение / запись в файл, но я не знаю, какие странные вещи могут произойти во время сбоя. Может быть, я просто параноик, пожалуйста, скажи мне, если так.
Есть ли лучший способ определить, в каком блоке кода происходит сбой?
2 ответа
"Могу ли я верить, что сообщение"Code block1 успешно выполнено "в любом случае действительно будет отображаться в моем файле журнала?"
Нет, вы не можете верить, что что-то наконец записывается в ваши файлы журналов, когда выполняется этот оператор, и ваша программа фактически находится в каком-то исключительном состоянии.
С flush()
вызов подразумевается со строкой, чтобы написать, шансы становятся лучше, но по-прежнему не будут гарантированы. Это зависит от исключительного условия, которое выполнила ваша программа.
Рассмотрим случай, когда ваша программа падает из-за неопределенного поведения, которое случайно испортило что-то в буферах или данных, используемых вашей программой. Logger
экземпляр класса. Кроме того, если вы столкнулись с условиями нехватки памяти, никакие гарантии не могут быть предоставлены для последующего выполнения кода, даже если он был перехвачен правильно.
Также обратите внимание:
Синхронная очистка обычно не нужна для ведения журналов в многопоточных приложениях. Синхронный вызов flush()
может изменить поведение фактически применяемых потоков и скрыть / скрыть условия гонки, которые появятся, как только будет отключено ведение журнала.
Если вы хотите быть уверены, что ваш текст был записан в файл журнала, вам нужно использовать std::endl, который выполняет сброс, который записывает любые буферы, используемые для устройства вывода.
Например:
std::cout << "write me!\n"; // no flush
std::cout << "write me!" << std::endl; // buffer flushed