Topic: Clarification of what container::max_size() means.
Author: "Leigh Johnston" <leigh@i42.co.uk>
Date: Sat, 26 Sep 2009 15:35:20 CST Raw View
Microsoft will not fix what I consider a bug in VC++ STL implementation
until there is clarification in the standard of what container::max_size()
actually means, or more specifically how it relates to
allocator::max_size().
The standard states that allocator::max_size() is the largest value that can
be passed to allocator::allocate whilst container::max_size() is largest
possible size() of the container. VC++ STL assumes that
container::max_size() is equivalent to allocator::max_size() which I think
is incorrect. g++ assumes that container::max_size() is different to
allocator::max_size() which I think is correct. When writing a custom
allocator it is possible that the allocator might return 1 for
allocator::max_size() even though you can allocate more than one element via
multiple calls to allocator::allocate (consider a non-contiguous chunk/pool
allocator).
Could we have clarification in the standard to satisfy Microsoft?
The VC++ bug is
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=490955
/Leigh
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "Bo Persson" <bop@gmb.dk>
Date: Sun, 27 Sep 2009 09:24:09 CST Raw View
Leigh Johnston wrote:
> Microsoft will not fix what I consider a bug in VC++ STL
> implementation until there is clarification in the standard of what
> container::max_size() actually means, or more specifically how it
> relates to allocator::max_size().
>
> The standard states that allocator::max_size() is the largest value
> that can be passed to allocator::allocate whilst
> container::max_size() is largest possible size() of the container.
> VC++ STL assumes that container::max_size() is equivalent to
> allocator::max_size() which I think is incorrect. g++ assumes that
> container::max_size() is different to allocator::max_size() which I
> think is correct. When writing a custom allocator it is possible
> that the allocator might return 1 for allocator::max_size() even
> though you can allocate more than one element via multiple calls to
> allocator::allocate (consider a non-contiguous chunk/pool
> allocator).
> Could we have clarification in the standard to satisfy Microsoft?
>
> The VC++ bug is
> https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=490955
>
> /Leigh
The committee has already considered another request to improve the
wording, but declined.
http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#197
I believe the intent was to have an (ball park) upper limit to the
allocation size. If you try to allocate more than
allocator::max_size(), you are certain that this will fail. This
doen't mean that max_size() - 1 will succeed.
For example, the std::allocator<T> supplied by Microsoft effectively
returns numeric_limits<size_t>::max() / sizeof(T), which is a gross
over estimation, considering that the OS reserves half the address
space for itself.
That's about how precise the function is.
Bo Persson
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "Leigh Johnston" <leigh@i42.co.uk>
Date: Mon, 28 Sep 2009 03:33:39 CST Raw View
Yes but my point is that container::max_size() is different to
allocator::max_size(). A custom allocator can return something more
useful than what most std::allocator implementations return.
Microsoft are treating container::max_size() as equivalent to
allocator::max_size() which is incorrect as allocator::max_size()
relates to a *particular* allocation request, not the sum of *all*
allocation requests (going off current wording in the Standard).
/Leigh
"Bo Persson" <bop@gmb.dk> wrote in message
news:7i9003F2odpauU1@mid.individual.net...
>
> Leigh Johnston wrote:
>>
>> Microsoft will not fix what I consider a bug in VC++ STL
>> implementation until there is clarification in the standard of what
>> container::max_size() actually means, or more specifically how it
>> relates to allocator::max_size().
>>
>> The standard states that allocator::max_size() is the largest value
>> that can be passed to allocator::allocate whilst
>> container::max_size() is largest possible size() of the container.
>> VC++ STL assumes that container::max_size() is equivalent to
>> allocator::max_size() which I think is incorrect. g++ assumes that
>> container::max_size() is different to allocator::max_size() which I
>> think is correct. When writing a custom allocator it is possible
>> that the allocator might return 1 for allocator::max_size() even
>> though you can allocate more than one element via multiple calls to
>> allocator::allocate (consider a non-contiguous chunk/pool
>> allocator).
>> Could we have clarification in the standard to satisfy Microsoft?
>>
>> The VC++ bug is
>> https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=490955
>>
>> /Leigh
>
> The committee has already considered another request to improve the
> wording, but declined.
>
> http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#197
>
>
> I believe the intent was to have an (ball park) upper limit to the
> allocation size. If you try to allocate more than
> allocator::max_size(), you are certain that this will fail. This
> doen't mean that max_size() - 1 will succeed.
>
> For example, the std::allocator<T> supplied by Microsoft effectively
> returns numeric_limits<size_t>::max() / sizeof(T), which is a gross
> over estimation, considering that the OS reserves half the address
> space for itself.
>
> That's about how precise the function is.
>
>
> Bo Persson
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "Leigh Johnston" <leigh@i42.co.uk>
Date: Mon, 28 Sep 2009 03:35:02 CST Raw View
Which behaviour is correct given the following code, g++ or VC++?
They cannot both be correct.
#include <iostream>
#include <list>
template <typename T>
struct hmm : std::allocator<T>
{
hmm() {}
hmm(const hmm& other) : std::allocator<T>(other) {}
template <typename U>
hmm(const hmm<U>& other) : std::allocator<T>(other) {}
typename std::allocator<T>::size_type max_size() const { return 1; }
template<class _Other>
struct rebind { typedef hmm<_Other> other; };
};
int main()
{
typedef std::list <int, hmm<int> > container;
container list;
list.push_back(1);
list.push_back(1);
std::cout << "container::size() = " << list.size() << std::endl;
std::cout << "container::max_size() = " << list.max_size() << std::endl;
std::cout << "container::allocator_type::max_size() = " <<
container::allocator_type().max_size() << std::endl;
}
g++ outputs:
container::size() = 2
container::max_size() = 4294967295
container::allocator_type::max_size() = 1
VC++ throws an exception on the second push_back.
They cannot both be correct.
/Leigh
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "Bo Persson" <bop@gmb.dk>
Date: Mon, 28 Sep 2009 18:45:34 CST Raw View
Leigh Johnston wrote:
> Which behaviour is correct given the following code, g++ or VC++?
> They cannot both be correct.
>
> #include <iostream>
> #include <list>
>
> template <typename T>
> struct hmm : std::allocator<T>
> {
> hmm() {}
> hmm(const hmm& other) : std::allocator<T>(other) {}
> template <typename U>
> hmm(const hmm<U>& other) : std::allocator<T>(other) {}
> typename std::allocator<T>::size_type max_size() const { return 1;
> } template<class _Other>
> struct rebind { typedef hmm<_Other> other; };
> };
>
> int main()
> {
> typedef std::list <int, hmm<int> > container;
> container list;
> list.push_back(1);
> list.push_back(1);
> std::cout << "container::size() = " << list.size() << std::endl;
> std::cout << "container::max_size() = " << list.max_size() <<
> std::endl; std::cout << "container::allocator_type::max_size() = "
> << container::allocator_type().max_size() << std::endl;
> }
>
> g++ outputs:
>
> container::size() = 2
> container::max_size() = 4294967295
> container::allocator_type::max_size() = 1
>
> VC++ throws an exception on the second push_back.
>
> They cannot both be correct.
>
> /Leigh
FWIW, this seems to be the behavior of g++ 3, where I have 3.4.6
looking like this:
/** Returns the size() of the largest possible %list. */
size_type
max_size() const
{ return size_type(-1); }
On the other hand, the latest 4.4.1 has changed this into:
/** Returns the size() of the largest possible %list. */
size_type
max_size() const
{ return _M_get_Node_allocator().max_size(); }
None of these seems extremely accurate, but using the allocator
max_size at least seems to be the current trend.
Bo Persson
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "Leigh Johnston" <leigh@i42.co.uk>
Date: Tue, 29 Sep 2009 12:00:43 CST Raw View
Looks like I will have to change my custom pool allocator max_size() to
return a stupidly large value instead of returning 1 even though the
standard says that max_size() "Returns: the largest value that can
meaningfully be passed to X::allocate()".
/Leigh
"Bo Persson" <bop@gmb.dk> wrote in message
news:7ic5rmF31k7uqU1@mid.individual.net...
> Leigh Johnston wrote:
>> Which behaviour is correct given the following code, g++ or VC++?
>> They cannot both be correct.
>>
>> #include <iostream>
>> #include <list>
>>
>> template <typename T>
>> struct hmm : std::allocator<T>
>> {
>> hmm() {}
>> hmm(const hmm& other) : std::allocator<T>(other) {}
>> template <typename U>
>> hmm(const hmm<U>& other) : std::allocator<T>(other) {}
>> typename std::allocator<T>::size_type max_size() const { return 1;
>> } template<class _Other>
>> struct rebind { typedef hmm<_Other> other; };
>> };
>>
>> int main()
>> {
>> typedef std::list <int, hmm<int> > container;
>> container list;
>> list.push_back(1);
>> list.push_back(1);
>> std::cout << "container::size() = " << list.size() << std::endl;
>> std::cout << "container::max_size() = " << list.max_size() <<
>> std::endl; std::cout << "container::allocator_type::max_size() = "
>> << container::allocator_type().max_size() << std::endl;
>> }
>>
>> g++ outputs:
>>
>> container::size() = 2
>> container::max_size() = 4294967295
>> container::allocator_type::max_size() = 1
>>
>> VC++ throws an exception on the second push_back.
>>
>> They cannot both be correct.
>>
>> /Leigh
>
> FWIW, this seems to be the behavior of g++ 3, where I have 3.4.6
> looking like this:
>
> /** Returns the size() of the largest possible %list. */
> size_type
> max_size() const
> { return size_type(-1); }
>
> On the other hand, the latest 4.4.1 has changed this into:
>
> /** Returns the size() of the largest possible %list. */
> size_type
> max_size() const
> { return _M_get_Node_allocator().max_size(); }
>
>
> None of these seems extremely accurate, but using the allocator
> max_size at least seems to be the current trend.
>
>
> Bo Persson
>
>
>
> --
> [ comp.std.c++ is moderated. To submit articles, try just posting with ]
> [ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
> [ --- Please see the FAQ before posting. --- ]
> [ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
>
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Sean Hunt <rideau3@gmail.com>
Date: Tue, 6 Oct 2009 12:57:15 CST Raw View
On Sep 29, 11:00 am, "Leigh Johnston" <le...@i42.co.uk> wrote:
> Looks like I will have to change my custom pool allocator max_size() to
> return a stupidly large value instead of returning 1 even though the
> standard says that max_size() "Returns: the largest value that can
> meaningfully be passed to X::allocate()".
>
> /Leigh
Perhaps you should submit to Microsoft (and file a G++ bug, from the
looks of it) that their implementation should respect the intended
meaning of allocator_type::max_size() for containers that only need to
allocate one element at a time anyways. A container like vector or
string would be expected to have a max_size of allocator_type::max_size
().
Sean Hunt
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]