2016-08-05 4 views
-1

Когда я запускаю следующий кодпочему vfork() дает ошибку сегментации

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
int main() 
{ 
    pid_t pid; 
    pid = vfork(); 
    printf("hello world\n"); 
} 
Output: 
hello world 
hello world 
hello world 
Segmentation fault 

Я знаю, что если Exec() или _exit() вызывается тогда vfork() может вести себя странным образом, если мы попытаемся изменить любую переменную, но кто-то может объяснить, что именно происходит? почему мир приветствия печатается 3 раза? Это потому, что printf() получает буферизацию? и, наконец, почему ошибка seg происходит именно тогда, когда родитель пытается вернуться?

+2

Если вы знаете, что он вызывает неопределенное поведение, почему вы спрашиваете о конкретном поведении? –

+2

, что является значением неопределенного поведения, его нельзя объяснить иначе, он будет определен –

+0

«Вести странно» не является хорошей характеристикой «имеет неопределенное поведение». В частности, неудача с segfault хорошо лежит в пределах практически произвольных границ неопределенного поведения. Так что печатайте «мир привет» три раза, независимо от того, есть ли в вашей программе какой-либо код, который мог бы объяснить что-либо о таком выходе. Вы не можете законно рассуждать о неопределенном поведении. –

ответ

1

(From POSIX.1) Функция vfork() имеет тот же эффект, что и вилка (2), за исключением того, что поведение не определено, если процесс, созданный vfork() либо изменяет какие-либо другие, чем переменную типа pid_t данные используется для хранения возвращаемого значения из vfork() или возвращается из функции , в которой был вызван vfork(), или вызывает любую другую функцию перед успешным вызовом _exit (2) или одного из семейства exec (3) функций ,

Похоже вы нарушаете все условия для использования vfork. Итак, это не сработает.

0

Кусок кода я написал это бедствие, и будет вести себя в неопределенном способе, но правдоподобное объяснение такого поведения может быть: -

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