2010-01-06 4 views
2

У меня проблема с boost shared_memory_object и mapped_region. Я хочу написать набор объектов (структур) в объекте памяти. Если структура содержит только символ, все в порядке; если я просто добавлю int в структуру, то, если я поставлю слишком много объектов (скажем, 70, что намного меньше предела блока), я получаю ошибку сегментации при записи.Boost shared_memory_object проблема с типами, отличными от char

До сих пор я только что видел примеры, когда простые символы записываются в общую память, но я ничего не читал о типах объектов, которые можно использовать. Мне интересно, должны ли I выполнить преобразование между моими объектами и потоком байтов или если такая функция уже существует. Или если я просто делаю что-то неправильно в своем коде. Закомментированные линии являются те, которые дают мне Segfault, когда ... удаленные комментарии

#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

+0

У меня такая же система и на самом деле, как поплавок и двойная работа тонкой , Почему они комментируют? –

ответ

3
pData += sizeof(Record); 

Эта линия является проблемой. Арифметические средства указателя означают, что изменения находятся в «единицах» основного типа указателя, в этом случае «Запись». Поэтому, если вы хотите увеличить до следующей записи, вы должны сделать pData ++, а не pData + = sizeof (Record), что увеличит указатель на байт (при условии, что sizeof (Record) - 8 - 8 * 8 = 64).

У вас есть подобный указатель арифметической ошибки в чеке размера:

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

Вы, вероятно, хотите что-то вроде:

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

Вы правы ... теперь все идет намного лучше. Спасибо! – Pietro