2013-09-30 138 views
1

我正在做一個家庭作業問題,在C中使用fork()和共享內存對象編寫collat​​z猜想的實現,在子進程中執行計算並在父進程中打印結果。我對C不是很熟悉,所以我在學習很多工具。使用gdb,當我嘗試訪問父進程中的對象時,我確定了一個段錯誤。我使用這是我的代碼:Segfault從共享內存中讀取

#include <sys/stat.h> 
#include <sys/types.h> 
#include <unistd.h> 
#include <sys/mman.h> 
#include <math.h> 

int main(int argc, const char* argv[]) 
{ 

const int SIZE = 4096; 
const char *name = "SM"; 
int shm_fd; 
void *ptr; 

pid_t child; 


if ((argc != 2) || (strtol(argv[1],NULL, 10) <= 0)) 
{ 
     printf("Invalid usage: requires 1 positive integer parameter\n"); 
     return -1; 
} 

child = fork(); 
if(child >=0) 
{ 
     if (child == 0) 
     { 
       shm_fd = shm_open(name, O_CREAT || O_RDWR, 0666); 
       ftruncate(shm_fd, SIZE); 
       ptr = mmap(0, SIZE, PROT_WRITE, MAP_SHARED, shm_fd, 0); 
       int currentval = strtol(argv[1],NULL,10); 
       sprintf(ptr,"%d",currentval); 
       ptr++;/* floor(log10(abs(currentval))) + 1;*/ 
       while (currentval > 1) 
       { 
         sprintf(ptr, ", "); 
         ptr += 2; 
         if (currentval % 2 == 1) 
         { 
           currentval = currentval * 3 + 1; 
           sprintf(ptr, "%d", currentval); 
           ptr++; 
         } 
         else 
         { 
           currentval = currentval/2; 
           sprintf(ptr, "%d", currentval); 
           ptr++; 
         } 
       } 
       sprintf(ptr, "\n"); 
       ptr+= 1; 
       return 0; 
     } 
     else 
     { 
       wait(); 

       shm_fd = shm_open(name, O_RDONLY, 0666); 
       ptr = mmap(0, SIZE, PROT_READ, MAP_SHARED, shm_fd, 0); 
       printf("%s\n",(char *)ptr); 
       shm_unlink(name); 
       return 0; 
     } 
} 
else 
{ 
     printf("error creating child process\n"); 
} 
return 0; 
} 

我從來沒有調試段錯誤之前,所以任何建議將是最受歡迎的。提前致謝。

回答

1

我發現了這個問題。它正在執行一個邏輯OR,而不是按位OR,因此創建了一個錯誤的文件描述符。

shm_fd = shm_open(name,O_CREAT || O_RDWR,0666);

應該已經

shm_fd =的shm_open(姓名,O_CREAT | O_RDWR,0666);

0

可以粘貼它用gdb創建的核心文件的回溯:

gdb -c <core file> <executable> 

它會打開在gdb的核心,然後輸入「BT」。這會讓你知道問題的確切位置。你也可以在這裏粘貼輸出。

+0

我認爲原因可能是你的mmap可能失敗。您正在使用指針,甚至不檢查錯誤情況。 mmap失敗時返回「-1」並設置錯誤編號。 – wabbit

+0

當我做轉儲時,我得到兩個核心文件。子是: '0在_IO_str_overflow_internal()0x00832f25從/lib/tls/libc.so.6 #1 0x00831abf在_IO_default_xsputn_internal()從/lib/tls/libc.so.6 #2 0x0080c4e8在vfprintf() from /lib/tls/libc.so.6 #3 0x00827b1b vsprintf()from /lib/tls/libc.so.6 #4 0x00814e3b sprintf()from /lib/tls/libc.so.6 #5 0x0804865d在main(argc = 2,argv = 0xbfea2e84)處於problem_3_21.c:42' – user2829815

+0

來自父代的bt:#0 0x0083c26b in strlen()from /lib/tls/libc.so.6 #1 0x0080f821 in /lib/tls/libc.so.6 #2 0x00814dc0 printf()from /lib/tls/libc.so.6 #3 0x08048748 in main(argc = 2,argv = 0xbfea2e84) at problem_3_21.c:68 ' – user2829815

1

我知道這無關你問,但因爲我碰到這個問題就來了,換了別人誰也可能會遇到可能會發現下面的有用:

在閱讀和打印系列在Collat​​z猜想,如果所採用的例子是8,上面的程序運行正常,因爲它的答案是:8,4,2,1 但是,如果你嘗試運行它10,答案是:10,5,16,8, 4,2,1,而上面的程序只會顯示:1,5,16,8,4,2,1。因爲它會一次讀取一個字符。所以這裏需要稍作修改。

int shift = 0; 
char store[sizeof(int)]; 
while (currentval > 1) 
{ 
     sprintf(ptr, ", "); 
     ptr += 2; 
     if (currentval % 2 == 1) 
     { 
       currentval = currentval * 3 + 1; 
     } 
     else 
     { 
       currentval = currentval/2; 
     } 
     sprintf(store, "%s", currentval); /* Convert the number to a string */ 
     sprintf(ptr, "%s", store); /* Store the string */ 
     shift = strlen(store); 
     ptr += shift; 
} 
sprintf(ptr, "\n"); 
ptr+= 1;