【问题标题】:Segmentation fault with System V shared memorySystem V 共享内存的分段错误
【发布时间】:2015-01-09 16:34:11
【问题描述】:

当我尝试使用strcpy 将一些字符复制到共享内存中时,我试图理解为什么这个简单的代码会导致分段错误:

#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <string.h>

int main()
{
    key_t key;
    int flag,id;
    char *buf;

    flag=IPC_CREAT|0600;
    if((key=ftok("myfile",12)) == -1 ) {
        perror("key");
        exit(2);
    }   
    printf("%X\n",key);

    if( (id=shmget(key,512,flag)) < 0) exit(1); 

    if( (buf=shmat(id,0,0)) < 0) exit(2);

    printf("PID %d, buf=%p\n",getpid(),buf);
    system("ipcs -m | grep 512");
    sleep(20);

    strcpy(buf,"Hello");
    sleep(100); 
    shmdt(buf);
    exit(0);
}

这是我得到的:

C1A0DAB
PID 12063, buf=0xffffffff8bc78000
0x0c1a0dab 271941746  username      600        512        1
Segmentation fault (core dumped)

另外进程的pmap表示:

00007f778bc78000      4K rw-s-    [ shmid=0x10358072 ]

我猜指针 buf 有问题,但目前我不知道如何更正。

有什么想法吗?

【问题讨论】:

  • 对于共享内存,代码需要:#include 和#include
  • this: '#include ' 用于进程间通信,而不是共享内存。 this: '#include ' 用于信号量,而不是共享内存
  • 如果没有正确的 #include 语句,此代码会导致编译器引发 17 个警告。 (并且警告需要更正)顺便说一句:链接时,是否访问了正确的库?
  • 需要 #include 用于 printf() 等。需要 #include 用于 getpid() 和 sleep()
  • 其中一个文件 (sys/shm.h??) 包括 sys/ipc.h 并且使用该头文件进行编译需要在#include 之前放置以下语句:'#define _XOPEN_SOURCE'或“#define _SVID_SOURCE”

标签: c shared-memory strcpy


【解决方案1】:

请在启用所有警告的情况下进行编译(例如,对于 gcc 和 clang,至少 -Wall)。

您缺少#include &lt;sys/shm.h&gt;,因此您的编译器假定smhat 返回一个int,而实际上它返回一个void*。如果 int 和void* 的大小不匹配,那就有问题了。

添加该包含,添加您在它时缺少的其他包含,它应该可以工作。

【讨论】:

  • 非常感谢,确实缺少#include
【解决方案2】:

注意您从编译器收到的警告。特别是,您会得到:

file.c:22:5: warning: implicit declaration of function ‘shmat’ [-Wimplicit-function-declaration]
file.c:22:13: warning: assignment makes pointer from integer without a cast

告诉你问题出在哪里——编译器假设shmat返回一个(32位)整数,而实际上它返回一个(64位)指针。所以你丢失了指针的前 32 位...

【讨论】:

    【解决方案3】:

    此信息来自http://web.cse.ohio-state.edu/~babic/Sem.shmem.new.pdf 需要考虑:

    重要: 未明确删除的信号量和共享内存留在系统中 在创建它们的进程终止后 甚至当用户注销时。

    由于 UNIX 支持有限数量的这些资源,它是 重要的是要确保所有创建 信号量和共享内存是remo 在注销之前。

    目录 /usr/class/cis660 包括 s 脚本文件 rsm .dat 提供方便的方式来删除所有 信号量和所有共享内存。

    单个信号量或共享备忘录 ry 可以使用 UNIX 命令删除 ipcrm –s sem# 或者 ipcrm –m 内存# ,其中 sem# 和 mem# 分别从 UNIX 命令中获取 ipcs ,其中列出了所有信号量和共享内存

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-12-06
      • 2011-01-14
      • 1970-01-01
      • 2018-06-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多