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?
On 9/9/07, Mark Mitchell <mark@codesourcery.com> wrote:
> Joe Buck wrote:
>
> >> 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.
> >
> > The key point is that the mechanism is hidden away. This might become
> > more of an issue with LTO, so the question is how to make such guarantees
> > make sense to an optimizer that can see the full program.
>
> Correct. The "malloc" attribute is only applicable to "malloc" because
> we can't see how "malloc" is implemented.
>
> >> 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?
> >
> > Maybe "pool", if exported, would have to be marked as aliasing the "new"
> > calls, possibly with some new attribute "malloc_implementation" or
> > something like that.
>
> It's worse than that:
>
> char *pool;
> void set_pool(char *p) { pool = p; }
> void *operator new(size_t s) { // return stuff from pool. }
>
> bool f() {
> char *p = new char[1024];
> set_pool (p);
> char *i = new char;
> return (p == i);
> }
>
> In other words, pointers from any part of the program can potentially be
> "laundered" through set_pool and return via the new operator. I don't
> see any way to make this fully safe, in general, without the limitation
> I imposed: the no-aliasing guarantee only applies to the values returned
> from the function called.
But in this case an access to *i through *p is invalid. [I suppose both
new calls are actually different implementations here] Each new
call starts lifetime of a new object, the previous object lifetime is
terminated. Even comparing both pointers here for this reason
would lead to undefined behavior.
I know it's easy to play games to trick optimizers into doing something,
but creating a not undefined testcase that goes wrong is hard ;) At
least iff you remember to transform 'malloc' attributes to a dynamic type
change if you inline a malloc.
Richard.