
I have encountered a bug when using BOOST_SP_USE_QUICK_ALLOCATOR with shared_ptr<> objects that are contained in a static container. This bug is verifiable with Visual Studio 2005 SP1 as well as MinGW GCC 4.2.1. As an example, I have created a static std::map, which pairs a long with a boost::shared_ptr<>. This is the scenario where I first encountered the bug. The boost preprocessor definition BOOST_SP_USE_QUICK_ALLOCATOR is defined. When the program exists, the application crashes during deallocation of the shared_ptrs. Under Visual Studio 2005, MSVCR80d.dllcrashes during _free_dbg() (and likewise MSVCR80.dll crashes during _free()). If the map is made a regular member instead of a static member, the program exits properly. In addition, if the boost quick allocator is disabled, the program exits properly. In my testing, I have found the key type is irrelevant, and what the shared_ptr points to also does not matter. The issue is with the Quick Allocator and the runtime cleanup of static objects. Here is an example console app. that will produce the problem. ------------------- // Boost Headers #define BOOST_SP_USE_QUICK_ALLOCATOR #include <boost/shared_ptr.hpp> // STL Map #include <map> // Test struct for Shared Pointer struct tTestItem { long x; }; // Test Class to use static map class tTestClass { public: tTestClass(long id) { boost::shared_ptr<tTestItem> xTestItem(new tTestItem()); m_TestMap.insert(std::make_pair<long, boost::shared_ptr<tTestItem>
(id, xTestItem)); }
private: static std::map<long, boost::shared_ptr<tTestItem> > m_TestMap; }; // Create Static Instance std::map<long, boost::shared_ptr<tTestItem> > tTestClass::m_TestMap; // Simple Main App int main() { tTestClass class1(1); tTestClass class2(2); return 0; } ------------------- Under Visual Studio, the problem can be detected as follows: In boost\detail\lwm_win32_cs.hpp, put breakpoints in (1) lightweight_mutex's ctor, (2) lightweight_mutex's dtor, and (3) scoped_lock's ctor. In boost\detail\quick_allocator.hpp, put breakpoints in allocator_impl<size, align_>'s (4) mutex(), (5) alloc(), and (6) dealloc(). Run the program. (5) [alloc()] fires. We're constructing class1, which is constructing a shared_ptr. (4) [mutex()] fires, as alloc() calls mutex(). (1) [lightweight_mutex's ctor] fires, as mutex() constructs a static lightweight_mutex. (3) [scoped_lock's ctor] fires, as alloc() then constructs a scoped_lock from the static lightweight_mutex. (5), (4), and (3) then fire as we construct class2 (the static lightweight_mutex has already been constructed, so (1) doesn't run again.) (2) [lightweight_mutex's dtor] fires, as we exit main() and destroy the static lightweight_mutex. (6) [dealloc()] fires, as we exit main() and destroy the static map and its contained shared_ptrs. (4) [mutex()] fires, returning a reference to the destroyed static lightweight_mutex. (3) [scoped_lock's ctor] fires, which calls EnterCriticalSection() with a trashed CRITICAL_SECTION, which causes the program to crash. Please let me know if I am misusing boost functionality in the above test application. Sincerely, Matthew Hunt