Перенаправление вывода cmd-скрипта в файл

Serab

Ситуация следующая.
Написан небольшой cmd-скрипт по типу следующего:
d:

cd d:\some_path
CoolProgram.exe parameters

cd d:\another_path
CoolProgram.exe parameters

Запустил его на ночь следующим образом:
script.cmd > Log

Сегодня пришел посмотреть.
В логах примерно следующее:

.......
2/30 Processing 00000002.jpg
3/30 Processing 00000003.jpg
4/30 Processing 00000004.jpg

d:\some_path>cd d:\another_path

d:\another_path>CoolProgram.exe parameters
...

Так вот там файлов было не 4. И все они по факту были обработаны. Но следов сообщений об этом в выходном файле нету. Все эти сообщения выводились через printf/wprintf.
Вот такие вот дела.
Есть идеи, почему вывод мог оказаться обрезанным? Вывода там довольно много, как минимум 3 умножить на 30 таких файлов.

Dasar

> Есть идеи, почему вывод мог оказаться обрезанным?
как вариант, используется буферизированный вывод, при этом файл не закрывается

Serab

Т.е. похоже, что приложение завершилось аварийно?

Dasar

Т.е. похоже, что приложение завершилось аварийно?
оно завершилось штатно, вот только буфер в памяти остался, и на винт не был сброшен.

Serab

И ты думаешь, что в библиотеке C могут не сбрасываться буферы printf при штатном завершении программы?

Dasar

И ты думаешь, что в библиотеке C могут не сбрасываться буферы printf при штатном завершении программы?
запросто. деструкторов же нет.
соответственно если нет fclose, то либа и не узнает о том, что вообще что-то завершается.

Serab

не fprintf, а printf.
mainCRTStartup я думаю, довольно интеллектуален для этого, нет?

Dasar

но так - это лишь гипотеза. похожие проблемы с буферизацией (не гарантирую, что именно в С) наблюдал несколько раз собственными глазами.

Serab

Не, ну я с тобой согласен, симптом на это намекает. Просто причину хочется нормальную придумать. А то так стремно программы писать =)
Да и в этом случае полечить было бы неплохо.

Dasar

mainCRTStartup я думаю, довольно интеллектуален для этого, нет?
скорее как раз нет
mainCrtStartup - это виндовая функция, которая про C-шные либы ничего не знает
про либы должна знать main
mainCrtStartup должна использоваться в тех случаях когда не хочется тащить(запускать) с-шную либу с собой
зы
тоже самое, что функции CreateThread и beginthread

Serab

mainCrtStartup - это виндовая функция, которая про C-шные либы ничего не знает
лол, это не виндовая функция. Это как раз функция поддержки библиотеки С. В ней вызываются инициализаторы глобальных переменных и конструкторы/деструкторы глобальных объектов.
Почему бы ей не отвечать за буферы printf?
Хотя сейчас посмотрю.
mainCrtStartup должна использоваться в тех случаях когда не хочется тащить(запускать) с-шную либу с собой
это вообще чушь несусветная :(

Serab

Хотя посмотреть будет сложновато, эти штучки могут регистрироваться через какой-нибудь atexit :(

Dasar

Это как раз функция поддержки библиотеки С. В ней вызываются инициализаторы глобальных переменных и конструкторы/деструкторы глобальных объектов.
так ты реализуешь main или mainCrtStartup?
если второе, то как раз - стандартное поведение mainCrtStartup вызываться не будет.
и соответственно, все что ты перечислил происходить не будет.
это вообще чушь несусветная
первая же ссылка гугла подтверждает мои ощущения, и в статье - mainCrtStartup используется именно для того, что я упоминул выше.
http://www.codeproject.com/KB/library/tlibc.aspx?display=Pri...
mainCRTStartup
Where does your console program start? Did I hear you say main? If you did, you said what I would have said before journeying into the inner Stationworkings of the C Runtime.
Windows isn't nice enough to provide your app with a ready-made argc and argv. All it does is call a void function specified in the EXE header. And by default, that function is called mainCRTStartup. Here is a simple example:
extern "C" void __cdecl mainCRTStartup
{
int argc = _init_args;
_init_atexit;
_initterm(__xc_a, __xc_z); // Call C++ constructors
int ret = main(argc, _argv, 0); // Don't handle environment strings
_doexit;
ExitProcess(ret);
}

Serab

так ты реализуешь main или mainCrtStartup?
Ну откуда вообще такие мысли? Я где-то писал, что "реализую" mainCRTStartup? Что вообще значит "реализовать mainCRTStartup" по-твоему? Кто этим занимается?

Serab

первая же ссылка гугла подтверждает мои ощущения, и в статье - mainCrtStartup используется именно для того, что я упоминул выше.
Ты продолжаешь. mainCRTStartup — это и есть часть стандартной сишной либы, которую как ты говоришь "не хочется тащить" ну что за бред?

Dasar

Ты продолжаешь. mainCRTStartup — это и есть часть стандартной сишной либы, которую как ты говоришь "не хочется тащить" ну что за бред?
ты статью читал?

Dasar

Ну откуда вообще такие мысли? Я где-то писал, что "реализую" mainCRTStartup? Что вообще значит "реализовать mainCRTStartup" по-твоему? Кто этим занимается?
извращенцы всякие, коих в этом форуме, каждый первый.

Serab

Да =)
Но я и до этой статьи сталкивался с этой твоей mainCRTStartup и на ассемблере писал программы. И знаю, что такое точка входа в приложение. И знаю, что если ты используешь библиотеку С (которая не нужна в ассемблерной программе то в твою прогу статически влинковывется часть, где написана функция mainCRTStartup, которая и является точкой входа, ее цель — запустить main, передать ей нормальные параметры, выполнить инициализацию, получить от main код завершения, выполнить деинициализацию, вернуть код завершения системе.
В твоей статье чуваки написали свою точку входа и чтобы запутать тебя, назвали ее так же. В принципе, имели право, потому что это тоже C-RunTime Startup, но это вводит в заблуждение. Тебя ввело.

Dasar

В твоей статье чуваки написали свою точку входа и чтобы запутать тебя, назвали ее так же. В принципе, имели право, потому что это тоже C-RunTime Startup, но это вводит в заблуждение. Тебя ввело.
насколько я понимаю они это сделали не просто так, а для того, чтобы меньше надо было бодаться с компилятором (там конечно можно сменить entrypoint, но это лишние телодвижения)
зы
признаю, что не точно сформулировал.
эта точка входа стандартная для микрософтовского компилятора, а не для винды в целом.

Serab

Ладно, не суть. Проблему не решает. Придется запустить еще раз, чтобы воспроизвести. Надо будет вручную сбрасывать буфер и выводить код завершения на экран, чтобы понять, что там стряслось.
В этом mainCRTStartup (в CRT Microsoft :smirk:) ничего связанного с буфером непосредственно не нашел, но это может регистрироваться в atexit.
Но посуди сам: ты в каждой программе, которая что-то выводит в stdout перед завершением сбрасываешь буферы? Ведь нет? Вот и мне кажется, что там либо аварийное завершение, либо :confused:
А хотя какой atexit? Это должно быть явно прописано. Надо пройтись отладчиком, он вроде может заходить во все деинициализаторы. Завтра займусь.

Dasar

Но посуди сам: ты в каждой программе, которая что-то выводит в stdout перед завершением сбрасываешь буферы? Ведь нет? Вот и мне кажется, что там либо аварийное завершение, либо
при аварийном завершении тоже должны сброситься
но вот при task kill не смогут

Serab

Ну аварийное аварийному рознь =) При каком-нибудь AV наверняка не сбрасываются.
Посмотри первый пост, там весь скрипт пошел дальше работать нормально, а вывод исчез _задолго_ до завершения работы программы. Что-то мистическое.

Dasar

а вывод исчез _задолго_ до завершения работы программы. Что-то мистическое.
может тупо память запоролась, а по случайному совпадению - это память оказалась, которая отвечает за вывод.

Serab

Не-не-не =) Я не буду писать код типа

a = b + c;
assert( a == b + c );
assert( b == a - c );

А, кстати, чуть не забыл. Дело происходило на VmWare Server :D

Dasar

Я не буду писать код типа
это достаточное условие, чтобы не было порчи памяти? )

Serab

Ну я как бы о том, что порча памяти — это жесть, это невозможно, я не верю :D

Dasar

Ну я как бы о том, что порча памяти — это жесть, это невозможно, я не верю
в преобразовании картинки запросто - т.к. координаты точки часто формируются по длинной цепочке, и поэтому легко вылететь за реальные размеры.

Serab

А, понял. Блин. Я о другой порче. Ну это да, это стремно.

istran

Недавно столкнулся с такой штукой в Linux.
На сколько я знаю, когда вывод происходит на экран, то буфер сбрасывается после '\n'.
Но при выводе в файл этого не происходит, но по идее должно сбрасываться при выходе
из программы, если она не завершается аварийно. В любом случае должна помочь функция
fflush( FILE* stream) после каждого вывода. Если выводишь по printf, то писать надо fflush( stdout).
Сорри, почитал тему, похоже, что я сегодня сыграл в КО)

Katya19

А эксперимент можно воспроизвести опять?

Serab

Да, я обязательно воспроизведу.
Но на это нужно время.
Да и по другим причинам этот "эксперимент" в любом случае придется воспроизводить еще очень много раз :crazy:

Serab

мда, сейчас поднял логи ночного билда, та же хрень наблюдается с завидным постоянством. К сожалению, cmd-скрипты запускались там только для этой задачи, поэтому аналогичных случаев найти не удалось. Вот :crazy:
Никаких у меня ебаных мыслей :( (c)
Оставить комментарий
Имя или ник:
Комментарий: