Size of the Boost shared vector keeps fluctuating

2019-08-07 17:08发布

问题:

I'm using a Boost based shared vector as IPC in my application.

In the application where I'm trying to read the shared memory, the size of the memory, m_size, or vector->size, keeps fluctuating between 2 ( i.e. the number of vectors I'm sharing ),and 0. I've no idea why this is happening. Maybe it's a synchronization issue? But even if this is the case, the size of the memory should not come to 0, as it's just reading whatever is there in the memory. It may be invalid ( i.e. old data ), but not 0.

Also, the application which writes to the shared memory repeatedly outputs 2, as the size of the shared memory...

What could be the error?

This creates additional problems, as I'm using the size of the shared memory to see if anything's been written inside it. If that is not correct, what other parameter can I use for it?

Kindly advise.

Thank you.

EDIT :

Application which Writes :

Creation

    shared_memory_object::remove("MySharedMemory");   // CREATION
m_bIsConnectionActive = false;
srvConnections = new PwServerCheckClass();

managed_shared_memory segment(create_only, "MySharedMemory", 65536);

const ShmemAllocator alloc_inst (segment.get_segment_manager());
vector_to_send = segment.construct<VECTOR_TO_SEND>("VECTOR_TO_SEND")(alloc_inst);

And now writing

    m_vector_to_send = srvConnections->getServerList();  //Vector whose contents are to be copied into shared vector
for(UINT loopCounter = 0; loopCounter < m_vector_to_send.size(); loopCounter++)
{
        SERVER_INFO_TYPE_CHAR TestSrv;
                    <Some code>
        vector_to_send->push_back(TestSrv); //Pushing vector back into shared memory
        wcout<<endl<<"Size of the vector is::"<<vector_to_send->size();

}

Application which reads :

Reading :

    managed_shared_memory segment(open_only, "MySharedMemory");
m_serverVector = segment.find<VECTOR_TO_SEND>("VECTOR_TO_SEND").first;
//int checkSrvSize = m_serverVector->shrink_to_fit;
if(m_serverVector == NULL)
    return;
int SrvSizeCheck = 1;
do
{
    if(!(m_serverVector->empty()))
        continue;
           for(auto it = m_serverVector->begin() ; it != m_serverVector->end() ; ++it, ++SrvSizeCheck)
           <Some code>

Here is where the behaviour becomes odd. Sometimes the vector->empty() is satisfied, though something is being written into the memory. Sometimes it goes past the empty() check and instead fails at the it != m_serverVector->end() condition. I don't know what to make out of it.

EDIT 2

I took a look at the documentation. According to it, for the semaphore section, the actual mutex is associated with the shared memory. So a struct is created, there is an array inside it, and some sempahores. And eventually it is this structure which is shared in memory.

In my case, I'm sharing a vector in shared memory. Would the same principle work, i.e. I create a structure with a vector inside it, alongwith the mutex members, and share it across? In this case, the structure to be mapped, and consequently the memory allocator, would be that of the struct and not that of the Vector, as I've done in my code, correct?

Kindly advise.

回答1:

Yes, you don't seem to have any locking in place.

Sharing memory between processes risks concurrent mutation/access. For this you need locking. Otherwise you introduce a data race and this invokes Undefined Behaviour as per the c++ standard.

In fact - in most real-life situations you'd actually need a mutex locking the creation of the shared memory area (unless you can prove that the creation is single-threaded).

Look at

  • named mutex (http://www.boost.org/doc/libs/1_55_0/doc/html/interprocess/synchronization_mechanisms.html#interprocess.synchronization_mechanisms.mutexes.mutexes_named_example)
  • anonymous mutex (http://www.boost.org/doc/libs/1_55_0/doc/html/interprocess/synchronization_mechanisms.html#interprocess.synchronization_mechanisms.mutexes.mutexes_anonymous_example)

If you want, you can use a semaphore to have an efficient message queue with 'message ready' notification. See BIP Semaphore

Finally, you can use lock-free access iff you use a lockfree container specifically designed for this, e.g. Shared-memory IPC synchronization (lock-free)