Boost 与 char 类型不同的共享内存对象问题

发布于 2024-08-17 06:13:49 字数 3541 浏览 3 评论 0原文

我对 boost共享内存对象和映射区域有问题。我想在内存对象中写入一组对象(结构体)。如果结构只包含一个字符,则一切正常;如果我只是向结构中添加一个 int ,那么如果我放入太多对象(比如说 70 个,远小于块的限制),我在写入时会出现分段错误。

到目前为止,我刚刚看到了将简单字符写入共享内存的示例,但我还没有读过任何有关可以使用的对象类型的内容。我想知道是否必须在我的对象和字节流之间进行转换,或者这样的函数是否已经存在。或者如果我只是在代码中做错了什么。注释行是在取消注释时给我带来段错误的行...

#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <cstring>
#include <cstdlib>
#include <string>
#include <vector>
#include <iostream>
#include <unistd.h>

struct Record {
    char c;
    int i;
//  float f;
//  double d;
//  char cs[32];
//  boost::interprocess::string is;
//  std::vector<int> v;

    Record() {}
    Record(int _k) { Init(_k); }

    void Init(int _k = 0) {
        c = _k + 65;
        i = _k;
//      f = _k + _k/100.0;
//      d = _k + _k/1000.0;
//      is = "interprocess string";
//      for(int j = 0; j < _k; ++j) v.push_back(j);
    }
};

int main(int argc, char *argv[])
{
   using namespace boost::interprocess;
   using std::cerr;
   using std::endl;

   int nObjects = 0;
   size_t blockSize = 1024;

   static std::string sharedObjName("MySharedMemory");      // why static?

   const int writer = 1, reader = 2, error = -1;
   int operation = error;

   if(argc >= 2) {
      if(argv[1][0] == 'w') operation = writer;
      if(argv[1][0] == 'r') operation = reader;
   }
   if(argc == 1) operation = writer;

   if(operation == writer)      // Writer process
   {
      cerr << "Number of objects to write = ";
      std::cin >> nObjects;

      // Remove shared memory on construction and destruction
      struct shm_remove {
         shm_remove() { shared_memory_object::remove(sharedObjName.c_str()); }
         ~shm_remove(){ shared_memory_object::remove(sharedObjName.c_str()); }
      } remover;

      shared_memory_object shm(create_only, sharedObjName.c_str(), read_write);

      shm.truncate(blockSize);

      mapped_region region(shm, read_write);

      offset_t shmSize;
      shm.get_size(shmSize);

      // Produce and write data
      Record *pData0 = static_cast<Record*>(region.get_address());
      Record *pData  = pData0;

      for(int i = 0; i < nObjects; ++i) {
         if(pData0 + blockSize - pData < signed(sizeof(Record))) {
            cerr << "Error: memory block full!" << endl;
            break;
         }
         pData->Init(i);
         pData += sizeof(Record);
      }

      //Launch child process
      pid_t pId = fork();

      if(pId == 0)
      {
         std::string s(argv[0]); s += " r";

         if(std::system(s.c_str()) != 0) {
            cerr << "Error launching reader process." << endl;
            exit(1);
         }
         exit(0);
      }
      else if(pId > 0)
      {
         sleep(2);
         cerr << "Writer has finished!" << endl;
      }
      else  // pId < 0
         exit(-1);
   }
   else if(operation == reader)         // Reader process
   {
      shared_memory_object shm (open_only, sharedObjName.c_str(), read_only);

      mapped_region region(shm, read_only);

      Record *pData = static_cast<Record*>(region.get_address());

      for(int i = 0; i < nObjects; ++i)  {
         // Print pData...
         pData += sizeof(Record);
      }
   }
   else
      exit(1);

   return 0;
}

谢谢您的任何提示!

MacOS X 10.6.2 - 海湾合作委员会 4.2 - 升压1.41.0

I have a problem with boost shared_memory_object and mapped_region. I want to write a set of objects (structures) in the memory object. If the structure contains just a char, everything is ok; if I just add an int to the structure, then if I put too many objects (let's say 70, so much less than the limit of the block) I get a segmentation fault when writing.

So far I have just seen examples where simple chars are written to the shared memory, but I have not read anything about the kind of objects that can be used. I am wondering if I have to make the conversion between my objects and a byte stream, or if such a function already exists. Or if I am just doing something wrong in my code. The commented lines are the ones that give me a segfault when decommented...

#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <cstring>
#include <cstdlib>
#include <string>
#include <vector>
#include <iostream>
#include <unistd.h>

struct Record {
    char c;
    int i;
//  float f;
//  double d;
//  char cs[32];
//  boost::interprocess::string is;
//  std::vector<int> v;

    Record() {}
    Record(int _k) { Init(_k); }

    void Init(int _k = 0) {
        c = _k + 65;
        i = _k;
//      f = _k + _k/100.0;
//      d = _k + _k/1000.0;
//      is = "interprocess string";
//      for(int j = 0; j < _k; ++j) v.push_back(j);
    }
};

int main(int argc, char *argv[])
{
   using namespace boost::interprocess;
   using std::cerr;
   using std::endl;

   int nObjects = 0;
   size_t blockSize = 1024;

   static std::string sharedObjName("MySharedMemory");      // why static?

   const int writer = 1, reader = 2, error = -1;
   int operation = error;

   if(argc >= 2) {
      if(argv[1][0] == 'w') operation = writer;
      if(argv[1][0] == 'r') operation = reader;
   }
   if(argc == 1) operation = writer;

   if(operation == writer)      // Writer process
   {
      cerr << "Number of objects to write = ";
      std::cin >> nObjects;

      // Remove shared memory on construction and destruction
      struct shm_remove {
         shm_remove() { shared_memory_object::remove(sharedObjName.c_str()); }
         ~shm_remove(){ shared_memory_object::remove(sharedObjName.c_str()); }
      } remover;

      shared_memory_object shm(create_only, sharedObjName.c_str(), read_write);

      shm.truncate(blockSize);

      mapped_region region(shm, read_write);

      offset_t shmSize;
      shm.get_size(shmSize);

      // Produce and write data
      Record *pData0 = static_cast<Record*>(region.get_address());
      Record *pData  = pData0;

      for(int i = 0; i < nObjects; ++i) {
         if(pData0 + blockSize - pData < signed(sizeof(Record))) {
            cerr << "Error: memory block full!" << endl;
            break;
         }
         pData->Init(i);
         pData += sizeof(Record);
      }

      //Launch child process
      pid_t pId = fork();

      if(pId == 0)
      {
         std::string s(argv[0]); s += " r";

         if(std::system(s.c_str()) != 0) {
            cerr << "Error launching reader process." << endl;
            exit(1);
         }
         exit(0);
      }
      else if(pId > 0)
      {
         sleep(2);
         cerr << "Writer has finished!" << endl;
      }
      else  // pId < 0
         exit(-1);
   }
   else if(operation == reader)         // Reader process
   {
      shared_memory_object shm (open_only, sharedObjName.c_str(), read_only);

      mapped_region region(shm, read_only);

      Record *pData = static_cast<Record*>(region.get_address());

      for(int i = 0; i < nObjects; ++i)  {
         // Print pData...
         pData += sizeof(Record);
      }
   }
   else
      exit(1);

   return 0;
}

Thank you for any hint!

MacOS X 10.6.2 -
gcc 4.2 -
Boost 1.41.0

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

柳絮泡泡 2024-08-24 06:13:49
pData += sizeof(Record);

那条线就是问题所在。指针算术意味着更改以基础指针类型(在本例中为 Record)的“单位”为单位。因此,如果您想递增到下一条记录,您应该执行 pData++,而不是 pData += sizeof(Record),这将使指针增加 64 字节(假设 sizeof(Record) 为 8 - 8*8 = 64)。

您在大小检查中遇到了类似的指针算术错误:

pData0 + blockSize - pData < signed(sizeof(Record))

您可能想要类似的东西:

blockSize/sizeof(Record)-(pData-pData0) <= 0
pData += sizeof(Record);

That line is the problem. Pointer arithmetic means changes are in "units" of the underlying pointer type, in this case Record. So if you want to increment to the next record, you should do pData++, rather than pData += sizeof(Record), which will increase the pointer by 64 bytes (assuming sizeof(Record) is 8 - 8*8 = 64).

You've got a similar pointer arithmetic error in the size check:

pData0 + blockSize - pData < signed(sizeof(Record))

You probably want something like:

blockSize/sizeof(Record)-(pData-pData0) <= 0
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文