2015-12-11 3 views
-7

Рассмотрим этот простой фрагмент кода:Not Getting Segmentation Fault

{ 
if(fork()) 
{ 
printf("Parent terminated\n"); 
} 
else 
{ 
    char *s = "hello world"; 
    *s = 'H'; 
printf("child terminated\n"); 
} 
wait(NULL); 
    return 0; 
} 

Когда я скомпилировать его я не получаю ошибку ошибки сегментации, как мы ожидаем, что при назначении на * s Выход: Родитель Отменено (без печати ребенок завершен)

Теперь, если я удаляю две строки char * s = ...... 'H', я получаю нормальный выход.
Может кто-нибудь объяснить это

+4

Зачем вам компилятор segfault при компиляции? – Olaf

+0

Серьезно: размышляйте о последствиях ** неопределенного поведения **. Кто бы вы ни называли «мы» - это не я или другие эксперты С. «Мы» всегда ожидаем носовых демонов. – Olaf

+0

@Olaf указатель не инициализирован. Когда эти две строки скомпилированы как независимая программа, мы получим seg fault – Anushman

ответ

3

Прежде всего, вы не обязаны получать ошибку сегментации или любое определенное поведение для запуска неопределенного поведения, например, для изменения строкового литерала. Хотя в Linux строковые литералы помещаются в постоянную память, поэтому их изменение в Linux обычно приводит к ошибке сегментации.

Так почему же этот код не вызывает segfault? Это так, но вы просто не видите этого, потому что вы раздвоены.

«Сегментация Fault (основной сбрасывали)» печатается сообщение вашей оболочки (напр., Баш), когда он обнаруживает, позвонив по телефону wait, когда процесс завершается он породил с сигналом SIGSEGV (Segfault). Однако ваша оболочка не получит никаких уведомлений о выходе дочерних процессов; ваш родительский процесс будет.

Ваш родительский процесс вызывает wait, чтобы подождать и получить код выхода при его завершении. Если вы не проигнорировали код выхода, перейдя в NULL, чтобы подождать, вы, вероятно, увидите, что код выхода -11 или -SIGSEGV.

Так что это segfault; ваш родительский процесс просто игнорирует уведомление ребенка о его нарушении.

+0

Спасибо .. и завершает работу дочернего процесса, если его родительский конец завершен – Anushman

+0

@Anushman Нет, процесс init (pid 1) наследует его. –

+0

Идеально, только что готов к copypasta в домашнее задание из-за завтра :( –

1

Во-первых, то, что говорят другие, верно: поведение не определено, и вы не можете зависеть от какого-либо поведения, в частности, при этом.

Однако я подозреваю, что происходит то, что на самом деле ребенок имеет, имеющий ошибку сегментации. Тем не менее, знакомое сообщение «Ошибка сегментации», которое вы видите в своем терминале, фактически напечатано вашей оболочкой, когда что-то вы запускаете seg faults.

Но, поскольку это дитя того, что вы побежали, ваша оболочка не заметила. Если вы сконфигурировали дампы ядра (например, ulimit -c unlimited), я ожидаю, что вы найдете основной файл из дочернего процесса, вызванного seg.