ЗЫЖ какое отношение имеет мой пример с кучей плюсов к fork'у? что удивительно - самое прямое: дело в том, что результат зависит от последовательности выполнения операций, и может выбираться компилятором произвольно. к примеру на любом процессоре начиная с iPentium мы можем выполнять 2 операции одновременно, чем компилятор и может воспользоватся. в данном случае ответ изменится. тут похожая ситуация - программа вызывает сама себя, причём ей абсолютно всё равно, дочка это или мамка. от этого-то и возникают непонятки. писать такой код - ИМХО моветон.
ситуация - программа вызывает сама себя, причём ей абсолютно всё равно, дочка это или мамка. от этого-то и возникают непонятки. писать такой код - ИМХО моветон.
Не совсем так.
Если это было бы так, то это была бы почти fork-бомба.
После fork, появляется новый процесс с тем же кодом, что и у родителя.
И конечно новый процесс начнет выполнять код не с самого начала, а со следующей инструкции после fork.
То есть функция printf будет вызвана ТРИ раза.
Один раз в отце до форка, второй раз в отце после форка и третий раз в сыне.
не, ну по идее
x=7+9=16.
Не знаю насчёт компиляторов... а на каких будет по-другому?
По поводу той задачки - даже не знаю... ну наверное будет tuk tuk tuk? Вообще я с системными программками пока не возился, fork() не использовал - пока без надобности было.
inneska написал:
Один раз в отце до форка, второй раз в отце после форка и третий раз в сыне.
Ага, ну я так и подумал. Ответ правильный? :)
tuk tuk tuk tuk 3 75.00%
Эээ, те, кто проголосовали на 4 раза - можете объяснить, почему так? :)
[quote=drBatty]ситуация - программа вызывает сама себя, причём ей абсолютно всё равно, дочка это или мамка. от этого-то и возникают непонятки. писать такой код - ИМХО моветон.
Не совсем так.
Если это было бы так, то это была бы почти fork-бомба.
После fork, появляется новый процесс с тем же кодом, что и у родителя.
И конечно новый процесс начнет выполнять код не с самого начала, а со следующей инструкции после fork.
То есть функция printf будет вызвана ТРИ раза.
Один раз в отце до форка, второй раз в отце после форка и третий раз в сыне.[/quote]
Я тоже так думал, прежде чем проверять, однако у меня в Fedora 10,
gcc-4.3.2, tuk печатается 4 раза.
не, ну по идее
x=7+9=16.
Не знаю насчёт компиляторов... а на каких будет по-другому?
по стандарту тут может получится всё что угодно - дело в том, что последовательность действий выбирается произвольно, т.е. компилятор вовсе не обязан выполнять операции так, как вам этого хочется (как вам кажется), т.е. компилятор может выполнить оба инкремента как он захочет, а вовсе не так как написано. к примеру он имеет прао выполнить сначала второй инкремент, а потом первый. может и сразу выполнить оба инкремента. а получается да, 16. у мну - тоже.
по стандарту тут может получится всё что угодно - дело в том, что последовательность действий выбирается произвольно, т.е. компилятор вовсе не обязан выполнять операции так, как вам этого хочется (как вам кажется), т.е. компилятор может выполнить оба инкремента как он захочет, а вовсе не так как написано. к примеру он имеет прао выполнить сначала второй инкремент, а потом первый. может и сразу выполнить оба инкремента. а получается да, 16. у мну - тоже.
Я в книжке читал, по-моему, в Страуструпе, что ВСЕГДА получается 16. И что операции выполняются последовательно. Слева направо.
А зачем компиляторы так делают? Чтобы всех запутать?
inneska, разница в том, что в первой буфер сбрасывался только один раз, при выходе, а во второй данные записывались асинхронно?
Да, у меня тоже возникло это предположение после чтения "man fork".
Если в варианте с printf, я, правда, всегда использую fprintf(stdout,...)
закончить строку формата символом '\n', то будут напечатаны три строки.
[quote=Peter]Если в варианте с printf, я, правда, всегда использую fprintf(stdout,...)
какая разница между этими функциями? ЕМНИП во всех известных мне реализациях stdio эти функции генерируются в один и тот-же код. или нет?[/quote]
Разница, пожалуй, эстетическая, но я вообще избегаю использования
умолчаний, так надёжнее.
А в примере с printf я сначала попробовал вызывать в потомке
tcflush(1,TCOFLUSH), но это не помогло.
в кривом коде ИМХО. уже сам вижу в чём тут разница... только лично я такого никогда не напишу...
Что по твоему кривого в коде? Скажи где конкретно кривизна. :cool:
В том, что нет ветвления после форка?
А если мне надо что бы мама и дочка после форка выполняли одинаковый код? Зачем тогда ветвление?
Вот так:
Если в варианте с printf, я, правда, всегда использую fprintf(stdout,...)
закончить строку формата символом '\n', то будут напечатаны три строки.
Между printf и fprintf(stdout,...) конечно разницы нет.
А вот если написать fprintf(stderr,...) то, будет три раза tuk.
А вот символ '\n' - действительно помогает. Но тогда получается три строки, а не одна строка с тремя tuk.
Peter написал:
А в примере с printf я сначала попробовал вызывать в потомке
tcflush(1,TCOFLUSH), но это не помогло.
Ты очень близок к правильному ответу. fflush тоже может помочь.
Главное только понять где и почему надо принудительно сбросить буфер.
Оказалось, что помогает именно fflush, а tcflush - нет. Я использовал
tcflush по привычке работать с COM-портом и начал с вызова её перед
fork, а когда это не помогло, попробовал вызвать tcflush в потомке.
Вызов же fflush перед fork действительно сбрасывает буфер.
Точнее, я сначала вызвал tcflush перед fork, потом в потомке, потом
внимательнее посмотрел "man fork" и добавил '\n'.
Однако tcflush "discards data", а fflush сбрасывает буфер в указанный поток.
По мне тут все просто. Потомок наследует все окружение родителя в том числе буфера. Поскольку после первого вызова printf последовал вызов fork, первый тук остался в буфере и передался дочернему процессу. Дочерний процесс прицепил свой тук к уже имеющемуся и распечатал вместо одного тука два. Одно из решений - вставить строку fflush(stdout) перед вызовом форка. Кстати, весь процесс очень хорошо виден если все туки пронумеровать (tuk1, tuk2, tuk3)