This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: [RFC] Marking C++ new operator as malloc?
Richard Guenther wrote:
>> Probably the most common use of a custom new is to allocate memory from
>> a user-controlled pool instead of the standard free store. Somewhere in
>> the program there will be a pointer to the complete pool, which aliases
>> every pointer returned by that version of new. Any such pool-based new
>> doesn't meet the requirements of the malloc attribute.
>
> That doesn't matter. What matters is object lifetime, which is properly
> preserved by a conforming pool allocator.
We have some terminology issues here. The definition of the malloc
attribute is:
> The `malloc' attribute is used to tell the compiler that a function
> may be treated as if any non-`NULL' pointer it returns cannot
> alias any other pointer valid when the function returns. This
> will often improve optimization.
The term "cannot alias" is not fully defined. It could mean "cannot
have the same value as any other pointer of the same type". It could
mean "cannot have the same value as any other pointer, when both
pointers are cast to `void *'". It could mean, a la "restrict", that
"no store through an expression based on this pointer can modify the
value read from via any expression based on any other pointer".
In the case of "malloc", and assuming that all of the machinery for
malloc is hidden away in some piece of the program we're not talking
about, all three definitions apply. Each pointer returned by malloc is
an island unto itself; there's no conforming way to get there except by
using the pointer just returned.
For, operator new, the same is true -- but we're more often able to see
the machinery for the allocator. For example:
char pool[N];
size_t next;
/* Never mind that the return memory isn't properly aligned here;
fixing the implementation is left to the reader. */
void *operator new(size_t s) {
void *p = pool + next;
next += s;
return p;
}
bool f() {
char *c = new char;
return (c == pool);
}
Now, I don't think we should allow the compiler to optimize the return
statement in "f" to "return false"? If operator new has attribute
malloc, then it may in fact do so -- even though the value returned
might be "pool" itself.
The same issue occurs if you call malloc from within the file that
defines malloc; the malloc attribute is saying something about what you
can do *if you cannot see the pool out of which the allocation is
occurring*. For malloc, which is fully squirreled away in libc
somewhere, this is probably safe in practice -- until LTO. For operator
new, it's a little dicier, since people do tend more often to replace it
in their own programs, and to put those replacements in inline functions
in header files where the compiler is liable to see more about what's
going on.
This seems like a useful optimization to me, and I understand that it
will work 99.99% of the time, and it's in the spirit of the standard --
but how do we actually make it safe? If the attribute only applied to
other values returned from the same function, then it would be safe --
but less useful. Can we do better?
--
Mark Mitchell
CodeSourcery
mark@codesourcery.com
(650) 331-3385 x713