共享内存能否存放带有指针的结构体?

http://www.cnblogs.com/knightly/p/3525456.html

共享内存能否存放带有指针的结构体?

  共享内存是第二种IPC工具。他允许两个无关的进程访问相同的逻辑内存。共享内存是在两个运行的程序之间传递数据的有效手段。尽管X/Open标准并没有要求,很可能绝大数的共享内存实现都是会将不同进程之间正在共享的内存安排在相同的物理内存中。

  共享内存为在多个进程之间共享与传递数据提供一个有效的手段。因为他并没有提供同步的方法,所以通常我们需要使用其他的机制来同步对共享内存的访问。通常,我们也许会使用共享内存来提供对大块内存区的有效访问,并且传递少量的消息来同步对此内存的访问。

  向共享内存存放带有指针的结构体时,当再次向共享内存取出这个指针的值时,会出现内存错误。

  结构体结构如下:  

  typedef struct base_array{
      int size ;
      int count ;
      struct base *data;
  }base_array;

  程序大致如下:

  int main(){

    shmid=shmget(key,SHARED_SEGMENT_SIZE,0666 | IPC_EXCL) ;  //创建共享内存

    if(fork()==0) {  //子进程

      shmptr=(base_array *)shmat(shmid,0,0);            //拿到共享内存的首地址

      L->size = number;                        //初始化L(base_array型)
         L->count = 0 ;
         for(i=0;i<number;i++){
            sprintf(string,"%d",i) ;
            strcpy(L->data[i].id,string) ;
            L->data[i].next = NULL ;
            L->count++ ;
         }

      memcpy(shmptr,&L,(sizeof(base)+sizeof(base_array))*(L.count));//将L的东西复制给shmptr

      sem_v(semid) ;                          //互斥

    }else{      //父进程

      shmptr=(base_array *)shmat(shmid,0,0);            //拿到共享内存的首地址

      sem_p(semid);                          //互斥

      printf("size=%d\n",shmptr->size);                //成功
                 printf("count=%d\n",shmptr->count);              //成功
                 printf("L->data[0]=%s\n",shmptr->data[0].id);          //失败

    }  

  }

  分析: size和count打印成功,而data[0].id打印失败。因为,size和count已经从子进程的内存中复制到了共享内存中了,而仅仅是把data的指针值复制到了共享内存里面,而真正的

      内容仍然在子进程的内存里面。当主进程去取这个值的时候,系统是在共享内存里面寻址,所以肯定会导致错误。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Windows 平台下,可以使用以下步骤存放结构体数据到共享内存中: 1. 定义需要存储的结构体数据类型。 2. 创建共享内存对象,可以使用 Windows API 函数 CreateFileMapping()。 3. 映射共享内存到当前进程的地址空间中,可以使用 Windows API 函数 MapViewOfFile()。 4. 在共享内存中存储结构体数据,可以使用 memcpy() 函数将结构体数据复制到共享内存的地址空间中。 5. 当需要访问共享内存中的结构体数据时,可以使用相应的指针类型进行访问。 下面是一个简单的示例代码: ```c++ #include <Windows.h> #include <iostream> // 定义需要存储的结构体数据类型 struct MyData { int i; double d; char str[20]; }; int main() { // 创建共享内存对象 HANDLE hMapFile = CreateFileMapping( INVALID_HANDLE_VALUE, // 使用无效的句柄创建 NULL, // 默认安全特性 PAGE_READWRITE, // 共享内存的读写权限 0, // 大小为0表示文件映射到整个文件 sizeof(MyData), // 共享内存的大小 L"MySharedMemory"); // 共享内存对象的名称 if (hMapFile == NULL) { std::cerr << "CreateFileMapping failed: " << GetLastError() << std::endl; return 1; } // 映射共享内存到当前进程的地址空间中 LPVOID lpMapAddress = MapViewOfFile( hMapFile, // 共享内存的句柄 FILE_MAP_ALL_ACCESS, // 共享内存的访问权限 0, // 偏移量为0表示从文件的开头开始映射 0, // 映射整个文件 sizeof(MyData)); // 映射的大小 if (lpMapAddress == NULL) { std::cerr << "MapViewOfFile failed: " << GetLastError() << std::endl; CloseHandle(hMapFile); return 1; } // 在共享内存中存储结构体数据 MyData data = { 123, 3.14, "Hello shared memory!" }; memcpy(lpMapAddress, &data, sizeof(MyData)); // 访问共享内存中的结构体数据 MyData* pData = reinterpret_cast<MyData*>(lpMapAddress); std::cout << "i = " << pData->i << std::endl; std::cout << "d = " << pData->d << std::endl; std::cout << "str = " << pData->str << std::endl; // 解除映射并关闭共享内存对象 UnmapViewOfFile(lpMapAddress); CloseHandle(hMapFile); return 0; } ``` 需要注意的是,由于共享内存是多个进程共享的,因此在访问共享内存时需要进行同步操作,以避免数据的竞争和冲突。例如,可以使用互斥量或信号量等同步机制来保护共享内存的数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值