Причина ошибки сегментации - PullRequest
4 голосов
/ 10 марта 2011

Я написал программу, используя системный вызов clone () с установленными CLONE_VM и CLONE_FILES.Я не могу понять, почему на выходе отображается ошибка сегментации.Может кто-нибудь, пожалуйста, исправьте мой код и сообщите мне причину этого.

#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<sched.h>
#include<stdlib.h>

int variable, fd;

int do_something() {  
    //   sleep(100);  
    variable = 42;  
    close(fd);  
    _exit(0);  
}  

int main(int argc, char *argv[]) {  
   void **child_stack;  
   char tempch;  

   variable = 9;  
   fd = open("test.file", O_RDONLY);  
   child_stack = (void **) malloc(16384);  
   printf("The variable was %d\n", variable);  

   clone(do_something, child_stack, CLONE_VM|CLONE_FILES, NULL);  
//   sleep(100);  

   printf("The variable is now %d\n", variable);  
   if (read(fd, &tempch, 1) < 1) {  
      perror("File Read Error");  
      exit(1);  
   }  
   printf("We could read from the file\n");  
   return 0;  
}  

Ответы [ 2 ]

4 голосов
/ 13 марта 2011

Вам нужно знать, какой стек направлений растет на вашем процессоре, и вам нужно знать, какой конец стека вы должны передать clone ().

С man clone:

Stacks grow downwards on all processors that run Linux (except the
HP PA processors), so child_stack usually points to the topmost
address of the memory space set up for the child stack.

Вы не передаете самый верхний адрес, вы передаете самый нижний адрес, и вы не (я предполагаю) на HP-PA.

Fix:

   child_stack = (void **) malloc(16384) + 16384 / sizeof(*child_stack);

P.S. Я удивлен числом очевидно неправильных ответов здесь.

  • Нет, закрыть из-за неверного дескриптора файла не аварийно завершает работу в любом UNIX и Существующая система Linux.
  • Нет, void* против void** не имеет никакого отношения к проблеме.
  • Нет, вам не нужно указывать адрес do_something, компилятор сделает это автоматически для вас.

И, наконец, да: вызов close, _exit или любой другой подпрограммы libc в потоке clone()d потенциально небезопасен, хотя здесь это не вызывает проблемы.

0 голосов
/ 10 марта 2011

Чтобы исправить это, нужно, чтобы дочерний стек действительно находился в стеке, т.е.

char child_stack [16384];

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

И даже тогда .. он работает с -g .., но падает с -O !!!

...