casseopea2 / gperftools

Automatically exported from code.google.com/p/gperftools
BSD 3-Clause "New" or "Revised" License
1 stars 0 forks source link

tcmalloc should define its new/delete as weak symbols #127

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago

One often desires to modify the behavior of tcmalloc by providing one's own 
version of new/delete/malloc/free that provide additional functionality but 
continue using tcmalloc's new/delete/malloc/free. For this to happen, 
tcmalloc should define its new/delete/malloc/free as weak symbols. 
Currently they are not weak - hence applications cannot provide their own 
versions of these symbols.

One can use this functionality in various ways. For example, one can have 
one's wrapper new/delete/malloc/free to allocate some additional memory at 
the beginning and provide a magic number there for debugging purposes. The 
de-allocation can check for that magic number to ensure that a valid 
pointer is being freed. A host of other debugging functionality can be 
added this way. Yet another way is to modify the functionality of new to 
not throw std::bad_allow exception but instead to abort() instead.

Note that if the linker is to choose between multiple weak symbols, it 
chooses the first one. So as long as one links against tcmalloc, all its 
symbols would be picked in preference to glibc. So there shouldn't be a 
possibility that the linker picks the malloc from tcmalloc, but free from 
glibc.

Original issue reported on code.google.com by mohit.a...@gmail.com on 25 Apr 2009 at 9:24

GoogleCodeExporter commented 9 years ago
This is an interesting idea, but I'm not sure I understand the motivation.  If 
you
don't want the tcmalloc symbols, just don't link in libtcmalloc.

Your examples suggest that you plan to override the weak tcmalloc 
new/delete/etc with
your own wrappers, and the have the wrappers call the tcmalloc new/delete/etc.  
As
far as I know, that is not possible.  Weak symbols are either resolved against, 
in
which case your wrapper is ignored, or they are not, in which case the tcmalloc
implementation is ignored.  There is no way, using weak symbols, to have both 
in the
same executable.

(As I mentioned in another thread, there's no need to modify tcmalloc code to 
abort()
on new failure -- use std::set_new_handler() instead.)

To my knowledge, there is no C or C++ language support for wrapping alloc
implementations like you wish to.  I think the only way to do this -- this is 
what
glibc does, for instance -- is to make tcmalloc's malloc/free/etc available 
under two
names: both tc_malloc and malloc, say.  We could declare malloc weak, and then 
if
users wanted to wrap malloc, they could define their own malloc which called 
tc_malloc.

I'll ask around here to see if there's any support for that.

Original comment by csilv...@gmail.com on 26 Apr 2009 at 6:52

GoogleCodeExporter commented 9 years ago

> Your examples suggest that you plan to override the weak tcmalloc 
new/delete/etc 
> with your own wrappers, and the have the wrappers call the tcmalloc 
new/delete/etc.

That is correct.

> As far as I know, that is not possible.  Weak symbols are either resolved 
against, 
> in which case your wrapper is ignored, or they are not, in which case the 
tcmalloc
> implementation is ignored.  There is no way, using weak symbols, to have both 
in 
> the same executable.

Actually, you can use tcmalloc from within the wrapper. The way to do that 
would be 
to use dlopen() and companions. That's typically how one puts wrappers around 
glibc 
calls.

> As I mentioned in another thread, there's no need to modify tcmalloc code to 
> abort() on new failure -- use std::set_new_handler() instead.)

Thanks for the tip - I indeed didn't know about this. However, this handler 
doesn't
seem to distinguish between the following calls:
       (1) char *ptr = new char[N];
       (2) char *ptr = new (std::nothrow) char[N];

I want to abort() when allocation fails only in the first call above (rather 
than 
throwing an exception). For the second form (that uses std::nothrow), the 
caller 
doesn't want an exception, and so is presumably happy to deal with the NULL 
return 
value itself (possibly by freeing some of the memory it has allocated and then 
retrying the allocation). So its preferable to not abort in the second case.

Original comment by mohit.a...@gmail.com on 26 Apr 2009 at 7:58

GoogleCodeExporter commented 9 years ago

I want to add that an alternative (and possibly cleaner and nicer) way to 
address 
this ticket would be to provide the following support in tcmalloc:

(1) A pre-allocation hook that allows one to modify the allocation size that 
the user 
requested.
(2) A post-allocation hook that allows one to even modify the return value of 
new/malloc. The idea is that the application would allocate some extra bytes in 
(1) 
and fill them up with a magic number. Then it'll return a pointer beyond this 
magic 
number in (2). The current MallocHook support in tcmalloc doesn't allow one to 
modify 
the return value.
(3) A hook that gets invoked on errors. This hook should get as an argument 
whether 
or not the caller is willing to see an exception (i.e., whether or not the 
caller 
invoked new with std::nowthrow).

Original comment by mohit.a...@gmail.com on 26 Apr 2009 at 8:10

GoogleCodeExporter commented 9 years ago
new/delete will be weak in the next perftools release.

Original comment by csilv...@gmail.com on 10 Aug 2009 at 6:39

GoogleCodeExporter commented 9 years ago
Fixed in perftools 1.4, just released.

Original comment by csilv...@gmail.com on 11 Sep 2009 at 6:45