--- boost/pool/pool.hpp~ 2007-11-25 13:07:19.000000000 -0500 +++ boost/pool/pool.hpp 2012-06-29 10:27:17.743017961 -0400 @@ -26,6 +26,10 @@ #include <boost/pool/poolfwd.hpp> +// std::numeric_limits +#include <boost/limits.hpp> +// boost::math::static_lcm +#include <boost/math/common_factor_ct.hpp> // boost::details::pool::ct_lcm #include <boost/pool/detail/ct_gcd_lcm.hpp> // boost::details::pool::lcm @@ -184,6 +186,15 @@ return details::pool::lcm<size_type>(requested_size, min_size); } + size_type max_chunks() const + { //! Calculated maximum number of memory chunks that can be allocated in a single call by this Pool. + size_type partition_size = alloc_size(); + size_type POD_size = math::static_lcm<sizeof(size_type), sizeof(void *)>::value + sizeof(size_type); + size_type max_chunks = (std::numeric_limits<size_type>::max() - POD_size) / alloc_size(); + + return max_chunks; + } + // for the sake of code readability :) static void * & nextof(void * const ptr) { return *(static_cast<void **>(ptr)); } @@ -194,7 +205,7 @@ explicit pool(const size_type nrequested_size, const size_type nnext_size = 32) :list(0, 0), requested_size(nrequested_size), next_size(nnext_size), start_size(nnext_size) - { } + { set_next_size(nnext_size); } ~pool() { purge_memory(); } @@ -209,7 +220,7 @@ // These functions are extensions! size_type get_next_size() const { return next_size; } - void set_next_size(const size_type nnext_size) { next_size = start_size = nnext_size; } + void set_next_size(const size_type nnext_size) { BOOST_USING_STD_MIN(); next_size = start_size = min BOOST_PREVENT_MACRO_SUBSTITUTION(nnext_size, max_chunks()); } size_type get_requested_size() const { return requested_size; } // Both malloc and ordered_malloc do a quick inlined check first for any @@ -438,7 +449,7 @@ if (ptr == 0) return 0; const details::PODptr<size_type> node(ptr, POD_size); - next_size <<= 1; + set_next_size(next_size << 1); // initialize it, store().add_block(node.begin(), node.element_size(), partition_size); @@ -462,7 +473,7 @@ if (ptr == 0) return 0; const details::PODptr<size_type> node(ptr, POD_size); - next_size <<= 1; + set_next_size(next_size << 1); // initialize it, // (we can use "add_block" here because we know that @@ -503,6 +514,9 @@ template <typename UserAllocator> void * pool<UserAllocator>::ordered_malloc(const size_type n) { + if (n > max_chunks()) + return 0; + const size_type partition_size = alloc_size(); const size_type total_req_size = n * requested_size; const size_type num_chunks = total_req_size / partition_size + @@ -531,7 +545,7 @@ store().add_block(node.begin() + num_chunks * partition_size, node.element_size() - num_chunks * partition_size, partition_size); - next_size <<= 1; + set_next_size(next_size << 1); // insert it into the list, // handle border case --- libs/pool/test/test_bug_6701.cpp (revision 78326) +++ libs/pool/test/test_bug_6701.cpp (revision 78326) @@ -0,0 +1,27 @@ +/* Copyright (C) 2012 Étienne Dupuis +* +* Use, modification and distribution is subject to the +* Boost Software License, Version 1.0. (See accompanying +* file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) +*/ + +// Test of bug #6701 (https://svn.boost.org/trac/boost/ticket/6701) + +#include <boost/pool/object_pool.hpp> +#include <boost/limits.hpp> +#include <boost/assert.hpp> + +int main() +{ + boost::pool<> p(1024, std::numeric_limits<size_t>::max() / 768); + + void *x = p.malloc(); + BOOST_ASSERT(!x); + + BOOST_ASSERT(std::numeric_limits<size_t>::max() / 1024 >= p.get_next_size()); + + void *y = p.ordered_malloc(std::numeric_limits<size_t>::max() / 768); + BOOST_ASSERT(!y); + + return 0; +}