boost::interprocess::node_allocator problem (VC8, release build)

I have a problem with node_allocator. The "repro" code: #include <boost/interprocess/managed_external_buffer.hpp> #include <boost/interprocess/allocators/node_allocator.hpp> #include <boost/interprocess/containers/list.hpp> //////////////// using namespace boost::interprocess; //////////////// enum { A_SHARED_MEMORY_SIZE = 4096 * 50, A_POOL_SIZE = 512, }; //////////////// static char g_static_buffer[A_SHARED_MEMORY_SIZE]; static managed_external_buffer g_sharm (create_only, g_static_buffer, A_SHARED_MEMORY_SIZE); //////////////// typedef node_allocator<int, A_POOL_SIZE, managed_external_buffer::segment_manager> int_allocator_t; typedef list<int, int_allocator_t> IntList; //////////////// struct T { IntList int_list; // T () : int_list (int_allocator_t(g_sharm.get_segment_manager())) {} }; typedef node_allocator<T, A_POOL_SIZE, managed_external_buffer::segment_manager> tis_allocator_t; typedef list<T, tis_allocator_t> TList; //////////////// int main() { TList* p = g_sharm.construct<TList>(anonymous_instance)(tis_allocator_t(g_sharm.get_segment_manager())); try { enum { N = 2 }; // Create objects then delete them for (int n = 0; n < N; n++) { // Create T-type objects for (int i = 0; i < A_POOL_SIZE; i++) { p->push_back(T()); // push new object to the list } p->clear(); // Delete all T objects } } catch (bad_alloc &) { cout << "No memory" << endl; } g_sharm.destroy_ptr(p); return 0; } The problem is the folowing. If N > 1, on _second_ "pass" (n=1) the bad_alloc exception is thrown while pushing new T object to the list. Why? I supposed that on any "pass", except the first one, no new T-type objects are actually created in shared memory. They should be taken from the pool instead. I.e., if there's enough memory on the first "pass", it must be also enough on any other one. The problem is specific for Visual Studio 2005, when producing release build (all options carry their default values). Thanks, Alex.

alexmark wrote:
I have a problem with node_allocator.
Thanks for the bug report. I will try to investigate it. It seems that VC8 and Interprocess don't work very well. I've seen other strange bugs around. I will need to see if there is an optimization hurting something or it's just a bug. But these type of errors only appear in VC8 and the problem is that they are only in release mode, so debugging tools are not very useful... Gimme a bit of time to see what's going on. Regards, Ion

Hi, I don't exactly reproduce your problem (my program just crashes in release mode) but I've found something tricky in my code: -> If we use raw pointer instead of offset_ptr there is no problem. -> If I make offset_ptr::set_offset function non-inline (taking it out of the class definition) my problem goes away. I suspect that function inlining in VC8 is hurting something. Can you try to make offset_ptr::sey_offset non-inline and report your results? I will try to guess if that's the only problem. Regards, Ion

Hi, I had some trouble with this, so I decided to try it out. The optimizations that cause the problem with MSVC is /Og and /Ob2 together (which are both part of /O2, optimize for speed). As Ion says it is function inlining that is the problem, since when i added __declspec(noinline) to set_offset it all worked like a dream. Here is a very ugly fix for this problem (just an ifdef and a __declspec): Index: offset_ptr.hpp =================================================================== RCS file: /cvsroot/boost/boost/boost/interprocess/offset_ptr.hpp,v retrieving revision 1.2 diff -u -r1.2 offset_ptr.hpp --- offset_ptr.hpp 7 Aug 2006 13:52:22 -0000 1.2 +++ offset_ptr.hpp 2 Feb 2007 12:44:25 -0000 @@ -51,6 +51,11 @@ void unspecified_bool_type_func() const {} typedef void (self_t::*unspecified_bool_type)() const; +#if (defined _MSC_VER) && (_MSC_VER >= 1200) + //a bug in VC8.0 (and maybe earlier?) makes having this + //inlined in release mode break things. + __declspec(noinline) +#endif void set_offset(const void *ptr) { //offset == 1 && ptr != 0 is not legal for this pointer When I install SP1 for VC8 I will let you know if this problem disappears. Lars P.S. I believe this may have been the problem I mentioned before that I had with interprocess/deque. Ion Gaztañaga wrote:
Hi,
I don't exactly reproduce your problem (my program just crashes in release mode) but I've found something tricky in my code:
-> If we use raw pointer instead of offset_ptr there is no problem. -> If I make offset_ptr::set_offset function non-inline (taking it out of the class definition) my problem goes away.
I suspect that function inlining in VC8 is hurting something. Can you try to make offset_ptr::sey_offset non-inline and report your results?
I will try to guess if that's the only problem.
Regards,
Ion _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

Hi! What I found out is the problem disappears when the additional option /Og- is set for release build. But /Og- option is reported by VC8 as obsolete so I'm not sure it's good way out. Moreover, I tested "repro" code with all variants of allocators available at boost::interprocess, both for "IntList" and for "TList". The code works ok in the following cases: - "int_allocator_t" (allocator for IntList) is either of type private_node_allocator or simple allocator and _does_not_ work correctly ("No memory" printed) when: - "int_allocator_t" is either of type cached_node_allocator or node_allocator. The type of "tis_allocator_t" does not affect the result. VC8 is claimed as more C++ standard compatible compiler than VC71, so I suppose we have two variants: - either the problem root is a bug in VC8 optimization routines - or boost::interprocess source code (or some boost code it uses) is "less compatible" with C++ standard than VC8 :) Regards, Alex. P.S. I tested the "repro" code having VS2005 SP1 installed. The "repro" code runs ok in any case when built using VC71. "Lars Hagström" <lars@update.uu.se> wrote in message news:45C332E0.3060304@update.uu.se...
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

Lars Hagström wrote:
Hi,
I had some trouble with this, so I decided to try it out. The optimizations that cause the problem with MSVC is /Og and /Ob2 together (which are both part of /O2, optimize for speed).
As Ion says it is function inlining that is the problem, since when i added __declspec(noinline) to set_offset it all worked like a dream. Here is a very ugly fix for this problem (just an ifdef and a __declspec):
I've also found that "get_offset" is also incorrectly inlined, since some Interprocess tests crash after applying the patch. I've also tagged "get_offset" as "nonline" and everything seems ok. I've uploaded a new offset_ptr.hpp version to CVS disabling inlining in VC8 for both functions. I hope this solves VC8-Interprocess problems. Regards, Ion

Hi, now it looks like working ok with no additional options applied. Thanks, gentlemen. Regars, Alex Markelov. "Ion Gaztañaga" <igaztanaga@gmail.com> wrote in message news:45C3A8DE.5090902@gmail.com... Lars Hagström wrote:
Hi,
I had some trouble with this, so I decided to try it out. The optimizations that cause the problem with MSVC is /Og and /Ob2 together (which are both part of /O2, optimize for speed).
As Ion says it is function inlining that is the problem, since when i added __declspec(noinline) to set_offset it all worked like a dream. Here is a very ugly fix for this problem (just an ifdef and a __declspec):
I've also found that "get_offset" is also incorrectly inlined, since some Interprocess tests crash after applying the patch. I've also tagged "get_offset" as "nonline" and everything seems ok. I've uploaded a new offset_ptr.hpp version to CVS disabling inlining in VC8 for both functions. I hope this solves VC8-Interprocess problems. Regards, Ion
participants (3)
-
alexmark
-
Ion Gaztañaga
-
Lars Hagström