【问题标题】:Segfault reading from shared memory从共享内存读取段错误
【发布时间】:2013-10-05 20:11:15
【问题描述】:

我正在处理一个作业问题,使用 fork() 和共享内存对象在 C 中编写 collat​​z 猜想的实现,在子进程中执行计算并在父进程中打印结果。我对C不是很熟悉,所以我学习了很多工具。使用 gdb,当我尝试访问父进程中的对象时,我发现了一个段错误。我正在使用这是我的代码:

#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;
}

我以前从未调试过段错误,因此欢迎任何建议。提前致谢。

【问题讨论】:

    标签: c segmentation-fault fork shared-memory


    【解决方案1】:

    我发现了问题。它执行的是逻辑 OR 而不是按位 OR,因此创建了一个错误的文件描述符。

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

    应该是

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

    【讨论】:

      【解决方案2】:

      我知道这与您提出的问题无关,但由于我遇到了这个问题,因此可能遇到的其他人可能会发现以下有用:

      在阅读和打印 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;            
      

      【讨论】:

        【解决方案3】:

        您能否粘贴使用 gdb 创建的核心文件的回溯:

        gdb -c <core file> <executable>
        

        它将在 gdb 中打开核心,然后键入 "bt" 。这将为您提供问题所在的确切位置。您也可以在此处粘贴该输出。

        【讨论】:

        • 我认为原因可能是您的 mmap 可能失败。您甚至没有检查错误条件就使用了指针。失败时的 mmap 返回“-1”并设置错误号。
        • 我在转储时得到两个核心文件。孩子是:0 0x00832f25 in _IO_str_overflow_internal () from /lib/tls/libc.so.6 #1 0x00831abf in _IO_default_xsputn_internal () from /lib/tls/libc.so.6 #2 0x0080c4e8 in vfprintf () from /lib/tls/libc.so.6 #3 0x00827b1b in vsprintf () from /lib/tls/libc.so.6 #4 0x00814e3b in sprintf () from /lib/tls/libc.so.6 #5 0x0804865d in main (argc=2, argv=0xbfea2e84) at problem_3_21.c:42
        • 来自父母的 bt :#0 0x0083c26b in strlen () from /lib/tls/libc.so.6 #1 0x0080f821 in vfprintf () from /lib/tls/libc.so.6 #2 0x00814dc0 in printf () from /lib/tls/libc.so.6 #3 0x08048748 in main (argc=2, argv=0xbfea2e84) at problem_3_21.c:68
        • 显然您从 mmap 获得的“ptr”是错误的。处理 mmap 的错误情况将帮助您解决分段问题。还要检查为什么 mmap 不起作用。
        猜你喜欢
        • 1970-01-01
        • 2020-06-20
        • 1970-01-01
        • 1970-01-01
        • 2014-10-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-17
        相关资源
        最近更新 更多