[Interprocess] Problem with reserve for vector of weak_ptr

Hello, I'm currently trying to store shared_ptr to data in a vector in fixed_managed_shared_memory. The problem is that my program is crashing during a weak_ptr assignment. Since the problem is difficult to explain, I designed a little example which crash every time for me : #include <iostream> #include <algorithm> #include <boost/interprocess/managed_shared_memory.hpp> #include <boost/interprocess/smart_ptr/shared_ptr.hpp> #include <boost/interprocess/smart_ptr/weak_ptr.hpp> #include <boost/interprocess/containers/vector.hpp> #include <boost/interprocess/allocators/allocator.hpp> using namespace boost::interprocess; struct Foo { Foo( int _x ) : x(_x) {} ~Foo() { std::cout << "Destructing a Foo with x=" << x << "\n"; } int x; /* ... */ }; typedef managed_shared_ptr<Foo, fixed_managed_shared_memory>::type FooSharedPtrType; typedef managed_weak_ptr <Foo, fixed_managed_shared_memory>::type FooWeakPtrType; typedef allocator<FooWeakPtrType, fixed_managed_shared_memory::segment_manager> FooWeakPtrAllocatorType; typedef vector<FooWeakPtrType , FooWeakPtrAllocatorType> FooWeakPtrVectorType; struct FooPtrOps { void operator()( const FooWeakPtrType & a ) { std::cout << a.lock()->x << "\n"; } }; int main() { //Remove existing segment shared_memory_object::remove("MySharedMemory"); //Create a new segment with given name and size fixed_managed_shared_memory segment(create_only, "MySharedMemory", 65536); //Initialize shared memory STL-compatible allocator const FooWeakPtrAllocatorType alloc_inst (segment.get_segment_manager()); //Construct a vector named "MyVector" in shared memory with argument alloc_inst FooWeakPtrVectorType *foo_vector = segment.construct<FooWeakPtrVectorType>("MyVector")(alloc_inst); FooSharedPtrType foo_ptr = make_managed_shared_ptr(segment.construct<Foo>(anonymous_instance)(2), segment); foo_vector->reserve(1); (*foo_vector)[0] = foo_ptr; foo_vector->reserve(2); (*foo_vector)[1] = foo_ptr; foo_vector->reserve(3); (*foo_vector)[2] = foo_ptr; std::cout << "foo_vector:\n"; std::for_each( foo_vector->begin(), foo_vector->end(), FooPtrOps() ); } The crash occurs during the last assignment. Investigating using gdb it seems that just before the assignment the value of (*foo_vector)[2] is : {m_pn = {m_px = 0x0, m_pi = 0x4000000000000fe2}} Obviously the m_pi address is wrong which cause the crash. I think it should be 0x0 like m_px. So, did I do something wrong or did I find a bug ? Thanks for your help. Gaëtan.

On 27/05/2010 18:44, Gaetan Gaumer wrote:
Hello, I'm currently trying to store shared_ptr to data in a vector in fixed_managed_shared_memory. The problem is that my program is crashing during a weak_ptr assignment. Since the problem is difficult to explain, I designed a little example which crash every time for me :
I'll look into this but... shouldn't you "resize" instead of "reserve? Best, Ion

2010/5/27 Ion Gaztañaga <igaztanaga@gmail.com>:
On 27/05/2010 18:44, Gaetan Gaumer wrote:
Hello, I'm currently trying to store shared_ptr to data in a vector in fixed_managed_shared_memory. The problem is that my program is crashing during a weak_ptr assignment. Since the problem is difficult to explain, I designed a little example which crash every time for me :
I'll look into this but... shouldn't you "resize" instead of "reserve?
Resize can trim the vector and I don't want it. I think "reserve" is the right function for my need. When I use push_back instead of operator[] there is no pb. For info I use gcc44 (don't have the version right now) on a 64b Linux. Best regards, Gaëtan

Resize can trim the vector and I don't want it. I think "reserve" is the right function for my need.
When I use push_back instead of operator[] there is no pb.
As Ion is probably just pointing out, there's a fundamental difference between resize and reserve. Resize modifies the "logical size" of the container, creating (by default construction) new entries, or removing (with destruction) entries. Reserve does not change the "logical size", and it's only use is as an implementation optimization (you can pre-assign internal buffer space, so that when adding new entries later on a memory allocation will already have occurred). For a vector, you can create one and then reserve one all you want, but the size is still 0 (until "push_back" or "insert", etc is performed), and indexing into the vector will be out of bounds. Read Josuttis C++ standard library book, or any good reference on the difference. Cliff

2010/5/28 Cliff Green <cliffg@codewrangler.net>:
Resize can trim the vector and I don't want it. I think "reserve" is the right function for my need.
When I use push_back instead of operator[] there is no pb.
As Ion is probably just pointing out, there's a fundamental difference between resize and reserve. Resize modifies the "logical size" of the container, creating (by default construction) new entries, or removing (with destruction) entries. Reserve does not change the "logical size", and it's only use is as an implementation optimization (you can pre-assign internal buffer space, so that when adding new entries later on a memory allocation will already have occurred).
For a vector, you can create one and then reserve one all you want, but the size is still 0 (until "push_back" or "insert", etc is performed), and indexing into the vector will be out of bounds.
Read Josuttis C++ standard library book, or any good reference on the difference.
Cliff
Ok, so I't my fault ;) I use mainly online reference (sgi.com and cplusplus.com ) and the fact that reserve() does not initialize memory is not so obvious in these docs. So thank you for your help. Gaetan.
participants (4)
-
Cliff Green
-
Gaetan Gaumer
-
Gaetan Gaumer
-
Ion Gaztañaga