Есть программа, работающая круглосуточно, периодически производящая некоторые вычисления, пишущая о своих успехах в текстовый файл. Эта запись реализована примитивным логгером, представляющем собой класс, содержащий функцию записи очередного сообщения в текущий файл лога(который меняется по прошествии определённого времени). Наблюдается странный плохо воспроизводимый глюк: при длительной работе в файле лога отсутствуют некоторые строки. Причём одни и те же. Т.е. должно быть
Здравствуйте, _vanger_, Вы писали:
__>Здравствуйте.
__>Есть программа, работающая круглосуточно, периодически производящая некоторые вычисления, пишущая о своих успехах в текстовый файл. Эта запись реализована примитивным логгером, представляющем собой класс, содержащий функцию записи очередного сообщения в текущий файл лога(который меняется по прошествии определённого времени). Наблюдается странный плохо воспроизводимый глюк: при длительной работе в файле лога отсутствуют некоторые строки. Причём одни и те же. Т.е. должно быть __>Не подскажете, с чем может быть связано такой поведение?
судя по коду, как минимум 2 варианта : либо fopen, либо vfprintf не отрабатывают успешно.
анализируйте коды ошибок и возвращаемое значение из vfprintf, в случае ошибки выводите в DebugOutputString, или куда-то еще.
а многопоточности у Вас там нет?
Здравствуйте, _Dreamer, Вы писали:
_D>судя по коду, как минимум 2 варианта : либо fopen, либо vfprintf не отрабатывают успешно. _D>анализируйте коды ошибок и возвращаемое значение из vfprintf, в случае ошибки выводите в DebugOutputString, или куда-то еще. _D>а многопоточности у Вас там нет?
Не отрабатывает только fopen. vfprintf и fclose завершаются успешно.
Программа однопоточная.
Были мысли, что дело в слишком частых вызовах fopen/fclose, но следующий код работает нормально:
int main()
{
bool first = true;
for( int i = 0 ; ; ++i )
{
if( FILE *file = fopen( "zzz.txt", first ? "w" : "a" ) )
{
first = false;
if( fprintf( file, "%d\n", i ) < 0 )
printf( "failed to write\n" );
if( 0 != fclose( file ) )
printf( "failed to close\n" );
}
else
{
printf( "failed to open\n" );
}
}
return 0;
}
Проверил на другом компиляторе под другой операционкой(Debian) — то же. Т.е. это особенность именно кода, а не поведения ОС при работе с файлами или реализации стандартной библиотеки. Но, где же, чёрт возьми, собака зарыта?
Единственный экземпляр логгера объявляется без изысков в logger.h:
static Logger logger();
а logger.h через stdafx.h цепляется к остальным заголовочным файлам.
Единственное обращение к логгеру — это вызов функции write, описанной выше.
Здравствуйте, _vanger_, Вы писали:
__>Не отрабатывает только fopen. vfprintf и fclose завершаются успешно. __>Программа однопоточная. __>Были мысли, что дело в слишком частых вызовах fopen/fclose, но следующий код работает нормально:
а что с кодами ошибок при неудочной fopen?
как говорит нам MSDN,
See _doserrno, errno, _sys_errlist, and _sys_nerr for more information on these, and other, error codes.
А зачем удаляется старый файл? Есть какой-то внешний процесс, который его архивирует? Если есть, то возможно, на время архивирования файл блокируется и поэтому его нельзя открыть.
Здравствуйте, AleksandrN, Вы писали:
AN>А зачем удаляется старый файл? Есть какой-то внешний процесс, который его архивирует? Если есть, то возможно, на время архивирования файл блокируется и поэтому его нельзя открыть.
Просто чтобы лог бесконечно не разрастался. Внешнего процесса, работающего с файлом нет.
Здравствуйте, _Dreamer, Вы писали:
_D>а что с кодами ошибок при неудочной fopen?
errno=EINVAL: Invalid argument.
Я разобрался. Дело было не в записи, а в непонимании межмодульного взаимодействия.
Прошлая реализация:
Единственный экземпляр логгера объявляется без изысков в logger.h:
static Logger logger();
а logger.h через stdafx.h цепляется к остальным заголовочным файлам.
приводила к тому, что для каждого объектного файла создавался свой экземпляр логгера. А слово static предотвращало конфликт имён, устанавливая внутреннее связывание.
string curLogName у лишних логгеров устанавливалась в "" конструктором по умолчанию. Код внутри
if( timer.timePassed( period ) || firstTime )
не выполнялся, т.к. firstTime — статическая и была уже изменена первым экземпляром логгера.
Сейчас сделал так:
в logger.cpp создаю экземпляр логгера, а в stdafx.h добавил