System V 共享内存的分段错误
Segmentation fault with System V shared memory
我试图理解为什么当我尝试使用 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
但我目前还不知道如何更正。
有什么想法吗?
请在启用所有警告的情况下进行编译(例如,对于 gcc 和 clang 至少 -Wall
)。
您缺少 #include <sys/shm.h>
,因此您的编译器假定 smhat
returns 是一个整数,而实际上它是 returns void*
。如果 int 的大小和 void*
不匹配,你就有问题了。
添加包括在内的内容,同时添加您遗漏的其他内容,它应该可以工作。
注意编译器发出的警告。特别是,您得到:
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
returns 一个(32 位)整数,而实际上它 returns 一个(64-位)指针。所以你丢失了指针的前 32 位...
此信息,来自http://web.cse.ohio-state.edu/~babic/Sem.shmem.new.pdf
需要考虑:
重要:
未明确删除的信号量和共享内存保留在系统中
在创建它们的进程终止后
甚至当用户注销时。
自 UNIX
支持数量有限的这些资源,它是
重要的是要确保所有创建
信号量和共享内存是remo
在注销之前。
目录
/usr/class/cis660包括
s 脚本文件
rsm
.dat 提供方便的方式来删除所有
一次信号量和所有共享内存。
个人信号量或共享备忘录
可以使用 UNIX 命令删除 ry
ipcrm –s sem#
要么
ipcrm –m 内存#
, 分别是从 UNIX 命令获得的 sem# 和 mem#
工控机
,其中列出了所有信号量和共享内存
我试图理解为什么当我尝试使用 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
但我目前还不知道如何更正。
有什么想法吗?
请在启用所有警告的情况下进行编译(例如,对于 gcc 和 clang 至少 -Wall
)。
您缺少 #include <sys/shm.h>
,因此您的编译器假定 smhat
returns 是一个整数,而实际上它是 returns void*
。如果 int 的大小和 void*
不匹配,你就有问题了。
添加包括在内的内容,同时添加您遗漏的其他内容,它应该可以工作。
注意编译器发出的警告。特别是,您得到:
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
returns 一个(32 位)整数,而实际上它 returns 一个(64-位)指针。所以你丢失了指针的前 32 位...
此信息,来自http://web.cse.ohio-state.edu/~babic/Sem.shmem.new.pdf 需要考虑:
重要: 未明确删除的信号量和共享内存保留在系统中 在创建它们的进程终止后 甚至当用户注销时。
自 UNIX 支持数量有限的这些资源,它是 重要的是要确保所有创建 信号量和共享内存是remo 在注销之前。
目录 /usr/class/cis660包括 s 脚本文件 rsm .dat 提供方便的方式来删除所有 一次信号量和所有共享内存。
个人信号量或共享备忘录 可以使用 UNIX 命令删除 ry ipcrm –s sem# 要么 ipcrm –m 内存# , 分别是从 UNIX 命令获得的 sem# 和 mem# 工控机 ,其中列出了所有信号量和共享内存