2010-01-06 15 views
2

J'ai un problème avec boost shared_memory_object et mapped_region. Je veux écrire un ensemble d'objets (structures) dans l'objet mémoire. Si la structure contient juste un caractère, tout va bien; si j'ajoute juste un int à la structure, alors si je mets trop d'objets (disons 70, tellement moins que la limite du bloc) j'obtiens une faute de segmentation en écrivant. Jusqu'à présent, je viens de voir des exemples où de simples caractères sont écrits dans la mémoire partagée, mais je n'ai rien lu sur le type d'objets qui peuvent être utilisés. Je me demande si I dois faire la conversion entre mes objets et un flux d'octets, ou si une telle fonction existe déjà. Ou si je fais juste quelque chose de mal dans mon code. Les lignes sont commentées celles qui me donnent une erreur de segmentation quand decommented ...Augmenter le problème shared_memory_object avec des types différents de char

#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; 
} 

Merci pour tout soupçon!

Mac OS X 10.6.2 - gcc 4.2 - Boost 1.41.0

+0

J'ai le même système et en fait à la fois flottant et double travail bien . Pourquoi sont-ils commentés? –

Répondre

3
pData += sizeof(Record); 

Cette ligne est le problème. L'arithmétique du pointeur signifie que les modifications sont en "unités" du type de pointeur sous-jacent, dans ce cas Record. Donc, si vous voulez incrémenter l'enregistrement suivant, vous devriez faire pData ++, plutôt que pData + = sizeof (Record), ce qui augmentera le pointeur de octets (en supposant que sizeof (Record) est 8 - 8 * 8 = 64).

Vous avez une erreur arithmétique de pointeur similaire dans la taille vérification:

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

Vous voulez probablement quelque chose comme:

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

Vous avez raison ... les choses vont beaucoup mieux maintenant. Merci! – Pietro