libstdc++, libsupc++, delete operators and valgrind

Mikolaj Golub trociny at FreeBSD.org
Sun Jan 27 15:35:08 UTC 2013


On Sun, Jan 20, 2013 at 02:19:55PM +0200, Mikolaj Golub wrote:
> Hi,
> 
> Some time ago I noticed that valgrind started to complain about
> "Mismatched free() / delete / delete []" for valid new/delete
> combinations.
> 
> For example, the following test program
> 
>   int main()
>   {
>       char* buf = new char[10];
>       delete [] buf;
>   
>       return 0;
>   }
> 
> produced a warning:
> 
> ==38718== Mismatched free() / delete / delete []
> ==38718==    at 0x100416E: free (vg_replace_malloc.c:473)
> ==38718==    by 0x4007BE: main (test.cpp:5)
> ==38718==  Address 0x2400040 is 0 bytes inside a block of size 10 alloc'd
> ==38718==    at 0x10047D7: operator new[](unsigned long) (vg_replace_malloc.c:382)
> ==38718==    by 0x40079D: main (test.cpp:4)
> 
> For some time I hoped that "someone" would fix the problem but seeing
> that after several upgrades it was still there I decided it is time to
> do some investigations.
> 
> Running the valgrind with "--trace-redir=yes -v" showed that valgrind
> activates redirections for new/delete symbols in libstdc++:
> 
> --6729-- Reading syms from /usr/lib/libstdc++.so.6 (0x1209000)
> ...
> --6729--    ------ ACTIVE ------
> ...
> --6729--     0x01260770 (operator new[](unsig) R-> (1001.0) 0x010041b0 operator new[](unsigned long, std::nothrow_t const&)
> --6729--     0x01260780 (operator new(unsigne) R-> (1001.0) 0x01004270 operator new(unsigned long, std::nothrow_t const&)
> --6729--     0x012608a0 (operator delete[](vo) R-> (1005.0) 0x01003e40 operator delete[](void*, std::nothrow_t const&)
> --6729--     0x012608b0 (operator delete(void) R-> (1005.0) 0x01003fa0 operator delete(void*, std::nothrow_t const&)
> --6729--     0x012dea90 (operator new[](unsig) R-> (1003.0) 0x01004770 operator new[](unsigned long)
> --6729--     0x012deab0 (operator new(unsigne) R-> (1003.0) 0x01004860 operator new(unsigned long)
> --6729--     0x012deca0 (operator delete[](vo) R-> (1005.0) 0x01003ef0 operator delete[](void*)
> --6729--     0x012e2b80 (operator delete(void) R-> (1005.0) 0x01004050 operator delete(void*)
> 
> But "delete" redirection is not triggered, while "new" is:
> 
> --6729-- REDIR: 0x12dea90 (operator new[](unsigned long)) redirected to 0x1004770 (operator new[](unsigned long))
> --6729-- REDIR: 0x19dd9a0 (free) redirected to 0x1004100 (free)
> ==6729== Mismatched free() / delete / delete []
> ==6729==    at 0x100416E: free (vg_replace_malloc.c:473)
> ==6729==    by 0x400715: main (test.cpp:5)
> ==6729==  Address 0x1ed7040 is 0 bytes inside a block of size 10 alloc'd
> ==6729==    at 0x10047D7: operator new[](unsigned long) (vg_replace_malloc.c:382)
> ==6729==    by 0x400701: main (test.cpp:4)
> 
> A little research revealed that in this case the delete operator from
> libsupc++ is called and valgrind does not provide redirections for the
> symbols in libsupc++.
> 
> When I added the redirections for libsupc++ to valgrind's
> vg_replace_malloc.c:
> 
>   #define  VG_Z_LIBSUPCXX_SONAME  libsupcZpZpZa           // libsupc++*
>   
>   FREE(VG_Z_LIBSUPCXX_SONAME, _ZdlPv,                __builtin_delete );
>   FREE(VG_Z_LIBSUPCXX_SONAME, _ZdlPvRKSt9nothrow_t,  __builtin_delete );
>   FREE(VG_Z_LIBSUPCXX_SONAME,  _ZdaPv,               __builtin_vec_delete );
>   FREE(VG_Z_LIBSUPCXX_SONAME,  _ZdaPvRKSt9nothrow_t, __builtin_vec_delete );
> 
> the issue was fixed:
> 
> --99254-- Reading syms from /usr/lib/libstdc++.so.6
> ...
> --99254--    ------ ACTIVE ------
> ...
> --99254--     0x012627c0 (operator new[](unsig) R-> (1001.0) 0x01004ce0 operator new[](unsigned long, std::nothrow_t const&)
> --99254--     0x012627d0 (operator new(unsigne) R-> (1001.0) 0x01004860 operator new(unsigned long, std::nothrow_t const&)
> --99254--     0x012628d0 (operator delete[](vo) R-> (1005.0) 0x01005b00 operator delete[](void*, std::nothrow_t const&)
> --99254--     0x012628e0 (operator delete(void) R-> (1005.0) 0x01005500 operator delete(void*, std::nothrow_t const&)
> --99254--     0x012c27e0 (operator new[](unsig) R-> (1003.0) 0x01004a80 operator new[](unsigned long)
> --99254--     0x012c2800 (operator new(unsigne) R-> (1003.0) 0x01004430 operator new(unsigned long)
> --99254--     0x012c29a0 (operator delete[](vo) R-> (1005.0) 0x01005800 operator delete[](void*)
> --99254--     0x012c3e40 (operator delete(void) R-> (1005.0) 0x01005200 operator delete(void*)
> ...
> --99254-- Reading syms from /usr/lib/libsupc++.so.1
> ...
> --99254--    ------ ACTIVE ------
> ...
> --99254--     0x01cae1f0 (operator delete[](vo) R-> (1005.0) 0x01005a00 operator delete[](void*, std::nothrow_t const&)
> --99254--     0x01cae200 (operator delete[](vo) R-> (1005.0) 0x01005700 operator delete[](void*)
> --99254--     0x01cae210 (operator delete(void) R-> (1005.0) 0x01005400 operator delete(void*, std::nothrow_t const&)
> --99254--     0x01cb73d0 (operator delete(void) R-> (1005.0) 0x01005100 operator delete(void*)
> ...
> --99254-- REDIR: 0x12c27e0 (operator new[](unsigned long)) redirected to 0x1004a80 (operator new[](unsigned long))
> --99254-- REDIR: 0x1cae200 (operator delete[](void*)) redirected to 0x1005700 (operator delete[](void*))
> 
> Now the question is: is it ok that now we have "new" operators being
> still called via libstdc++ while "delete" operators being called
> directly from libsupc++?
> 
> If it is ok, is the proposed solution with adding redirects for
> libsupc++ is a right way to fix the valgrind?
>

Ok, I think it is a good idea to add to valgrind replacements for
libsupc++ in any case, as it is possible to explicitly link in
libsupc++, if one does not need full libstdc++ features. I reported
with the patch to valgrind-freebsd:

https://bitbucket.org/stass/valgrind-freebsd/issue/7/add-replacements-for-libsupc

-- 
Mikolaj Golub


More information about the freebsd-stable mailing list