嘿我正在尝试在两个进程之间创建一个共享对象。并尝试从每个进程中读取和更改它们。这是我的简单结构。
编辑:我在我的结构中添加了一个构造函数。
struct shared{
shared(){
value = 10;
name = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
}
int value;
string name;
};
我在调用fork()之前和之后都试过调用shmat()但是没有任何改变它仍然会给出分段错误。
编辑:并在shmat()之后添加一个检查以查看它是否失败。
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <iostream>
#include <sys/shm.h>
#include <string.h>
using namespace std;
struct shared{
shared(){
value = 10;
name = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
}
int value;
string name;
};
int main(){
int shm_id = shmget(IPC_PRIVATE,sizeof(shared),0);
if(shm_id == -1){
cout<<"shmget() failed "<<endl;
return -1;
}
pid_t pid = fork();
if(pid == -1){
cout<<"fork() failed "<<endl;
return -2;
}
shared* sharedPtr = (shared*)shmat(shm_id,0,0);
if(sharedPtr == 0){
cout<<"shmat() failed "<<endl;
}
cout<<"Setting up the object: "<<endl;
sharedPtr->value = 5;
sharedPtr->name = "aaaaaa: ";
if(pid == 0){ //Child process
cout<<"Child process: "<<endl;
sharedPtr->value = 10;
sharedPtr->name = "bbbbbbb: ";
cout<<"Changed the object "<<endl;
return 0;
}
if(pid != 0){ //Parent process
sleep(1);
cout<<"Parent process: "<<endl;
cout<< sharedPtr->name << sharedPtr->value<<endl;
}
return 0;
}
但我仍然遇到分段错误。
答案 0 :(得分:4)
指针(if(sharedPtr == 0){
)的有效性检查发生在sharedPtr->value
中已经取消引用指针之后。因此,您可能会获得此行为,因为您正在取消引用空指针。点击之后>>使用指针。
此外,您不能像这样使用共享内存。您将获得一个静态大小的共享内存指针,表示与未初始化的字符串和int相当的内存,请考虑这一点。你基本上有这个:
int : size -> 4 bytes
empty string : size -> 32 bytes
(From here,系统相关)。然后,当您执行此(shared*)shmat(shm_id,0,0)
和此sharedPtr->name = "aaaaaa: "
时,您在此结构中创建的string
从未调用其构造函数,因此未正确创建。当你执行operator=
时,你试图使用一个在任何地方都不存在的函数,因为你调用它的对象没有被正确构造。如果您使用的是原始共享内存,则需要非常小心如何使用它以及占用的内存大小。您还可以考虑使用内存控制器来帮助您,例如boost::interprocess
。
答案 1 :(得分:3)
由于共享内存密钥不正确,导致崩溃。
但实际上你有各种严重程度的列表问题:
1)IPC_PRIVATE
不合适。你需要像这样使用ftok()
:
key_t key;
if ((key = ftok("/path/to/existing/file", 'R')) == -1) {
cerr << "ftok() failed: " << strerror(errno) << "\n";
return -1;
}
2)此检查应在shmget()
致电后立即执行。
if(shm_id == -1){
cout<<"shmget() failed "<<endl;
return -1;
}
3)使用strerror(errno)
将失败描述作为字符串
4)以下是您的主题https://stackoverflow.com/a/22557543/9187525
的示例 5)shmat()
失败时返回-1
,因此您的检查不正确。
6)std::string
通常不合适,因为它使用的是其他进程看不到的堆。根据您的C ++标准版本和字符串的长度,您将崩溃。有关详细信息,请参阅小字符串优化(SSO)。
7)在创建共享内存段以调用默认ctor之后,您需要调用placement new
。
8)shmget()
已过时,您可能希望将mmap()
用于共享内存,如果使用C ++,则可能更好使用相应的boost
库。
答案 2 :(得分:0)
您需要在调用shmget
:
// read/write permissions ---------------------vvvv
int shm_id = shmget(IPC_PRIVATE,sizeof(shared),0666);
然后,您需要在Shred内存段中实际分配对象。
获得指针后,需要使用placement new
创建对象:
new (sharedPtr) shared{}; // allocate the object in the shared memory segment
请注意,在子进程中更改后,字符串会在父进程中更新,但我认为这与字符串实现本身有关,而不是共享内存管理。 (如果我错了,请纠正我)