Re: This HAS to be UB...
On Oct 4, 7:13 am, "Chris M. Thomasson" <n...@spam.invalid> wrote:
"James Kanze" <james.ka...@gmail.com> wrote in message
news:7878ab49-834f-4bbc-b687-efdd8f31f1f3@z66g2000hsc.googlegroups.com...
On Oct 2, 9:52 pm, "Chris M. Thomasson" <n...@spam.invalid> wrote:
Keep in mind that I am a C programmer; well, anyway here is
the C++ program...
It looks to me like you're attacking some fairly tricky stuff.
You'd probably be better of starting with something simpler if
you're still learning C++. However...
I was exploring the feature in C++ delete operator in which
the size of the allocation is returned along with the pointer
to allocated memory. One could create heavily optimized custom
memory allocator using that important piece of information.
Certainly. It could be, in certain cases. But you're using a
fairly advanced feature of C++, one that many experienced C++
programmers aren't too familiar with. *IF* you're basically a C
programmer, and not too familiar with C++, you should probably
gain that familiarity first.
[...]
In practice, exception specifications are not really that
useful, except when they're empty. (It's very important in
certain cases to know that a function cannot throw any
exceptions, but it's rarely useful to know that it can't
throw certain types of exceptions.)
I thought it would be prudent to give the overloaded operator
new an exception specification of `std::bad_alloc'. Also, I
wanted to give an empty specification to the overload of
operator delete. As to how useful it is... Well, I don't
quite know.
Given that the standard does use that exception specifier for
the global operator new, it's probably a good idea to follow
suite. But I don't think that it's really that useful, and in
general, I wouldn't bother unless the specifier were empty.
(Note that the contract of the operator new function is slightly
different if it has an empty exception specifier. Unless it has
an empty specifier, operator new() and operator new[] may not
return a null pointer; if the version chosen has an empty
specifier, they can.)
void* const mem = ::operator new(size);
std::printf("custom_allocator::allocate(%p, %lu)\n",
(void*)mem, (unsigned long)size);
return mem;
}
static void deallocate(void* const mem, std::size_t size)
throw() {
std::printf("custom_allocator::deallocate(%p, %lu)\n",
(void*)mem, (unsigned long)size);
::operator delete(mem);
}
};
template<typename T>
struct allocator_base {
static void* operator new(std::size_t size)
The static isn't really necessary: allocation and
deallocation member functions (operator new and operator
delete) are always static, whether you declare them so or
not. (On the other hand, it doesn't hurt.)
Its a habit of mine. Also, using printf in C++ is another habit.
The static doesn't hurt. Using printf is a very bad habit,
however.
throw(std::bad_alloc()) {
return custom_allocator::allocate(size);
}
static void* operator new[](std::size_t size)
throw(std::bad_alloc()) {
return custom_allocator::allocate(size);
}
static void operator delete(void* mem)
Just curious: since you require the size in delete[], why don't
you require it here? Derivation can mean that the size isn't a
constant, e.g.:
class Base : public allocator_base< Base >
{
// ...
} ;
class Derived : public Base
{
// ...
} ;
Base* p = new Derived ;
// ...
delete p ;
(This supposes, of course, that Base has a virtual destructor.)
[...]
_____________________________________________________________________=
_
On GCC I get the following output:
custom_allocator::allocate(00246C50, 2234)
custom_allocator::deallocate(00246C50, 2234)
custom_allocator::allocate(00247760, 11174)
custom_allocator::deallocate(00247760, 11174)
On MSVC 8 I get:
custom_allocator::allocate(00362850, 2234)
custom_allocator::deallocate(00362850, 2234)
custom_allocator::allocate(00366B68, 11170)
custom_allocator::deallocate(00366B68, 2234)
Are they both right due to UB? WTF is going on? GCC seems to
be accurate at least... DAMN!
Well, there's no undefined behavior. You're program seems
perfectly legal and well defined to me. It looks like a bug in
VC++, see =A712.5/5:
It definitely looks like a bug is MSVC++. I get erroneous
behavior on versions 6 through 9.
It's quite possible. This is such a rarely used feature, I
doubt that it gets much testing. (In practice, I don't think
I've ever used new[]/delete[] in over 15 years of C++.)
When a delete-expression is executed, the selected
deallocation function shall be called with the address
of the block of storage to be reclaimed as its first
argument and (if the two-parameter style is used) the
size of the block as its second argument.
And I can't think of any way of interpreting "the size of the
block" to mean anything other than the size requested in the
call to operator new.
I thought that MSVC was crapping out because `allocator_base'
was a template. So I created another little test which
hopefully has all the bugs fixed:
_________________________________________________________________________=
_
[...[
_________________________________________________________________________=
_
On every version of GCC I have, I get the following output on
a 32-bit machine:
custom_allocator::allocate(00246C50, 1028)
custom_allocator::deallocate(00246C50, 1028)
custom_allocator::allocate(002472A8, 2240)
custom_allocator::deallocate(002472A8, 2240)
custom_allocator::allocate(002472A8, 11204)
custom_allocator::deallocate(002472A8, 11204)
On every version of MSVC, I get:
custom_allocator::allocate(00365B28, 1028)
custom_allocator::deallocate(00365B28, 1028)
custom_allocator::allocate(00362850, 2240)
custom_allocator::deallocate(00362850, 2240)
custom_allocator::allocate(00366FA8, 11204)
custom_allocator::deallocate(00366FA8, 2240)
Well, MSVC has a fairly nasty bug indeed. Anyway, what do you
think James?
It looks like an error in the compiler, but it's certainly a
minor one, since it concerns a feature that has no real use in
practice.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34