https://bugs.kde.org/show_bug.cgi?id=520170
--- Comment #2 from Michael Catanzaro <[email protected]> --- (In reply to Paul Floyd from comment #1) > Let's say your app links with liba and libb and they link > > liba -> dynamic libstdc++.so > libb -> static libstdc++.a The allocation and deallocation both occur in vte at termpropsregistry.cc:199, so at least there is only one library involved. > 2. If you use "identical code folding" then the linker might be seeing that > deallocation functions have identical machine code and only generating one > version. I don't think vte or freedesktop-sdk uses any special linker flags to enable such behavior, so if it's not something that ld.bfd performs by default, then that seems unlikely? > 3. If you use tcmalloc, that manually does identical code folding and only > generates one alias for free/delete/delete[]. No tcmalloc involved. Thanks for the tips. Looks like this is going to be pretty hard to track down. :( I don't have experience with reading assembly code, and the disassembled function where the allocation and deallocation occurs is pretty complicated at 2377 lines long, since it contains lots of inlined C++ functions. But at least it's the same function for both the allocation and deallocation, _ZN3vte8property8Registry12install_manyESt16initializer_listINS1_8PropertyEE. I'm going to attach the disassembly. Although I can only barely understand what I see, I do notice something interesting: there is a correspondence between the target of the call instructions and gobbledygook in vg_replace_malloc.c. So despite my inexperience, that seems clearly interesting. At least it *almost* explains why we wind up where we do. For example, the disassembly contains: 0x00007ffff64c95f9 <+185>: call 0x7ffff647bf40 <_ZdlPvm@plt> and the same at +1567 and +2203. And hey! that _ZdlPvm is a match for the /*------------------- C++14 delete sized -------------------*/ section of vg_replace_malloc.c: // operator delete(void*, unsigned long) #elif __SIZEOF_SIZE_T__ == 8 DELETE_SIZED(VG_Z_LIBSTDCXX_SONAME, _ZdlPvm, __builtin_delete, DeleteSized ); DELETE_SIZED(VG_Z_LIBCXX_SONAME, _ZdlPvm, __builtin_delete, DeleteSized ); DELETE_SIZED(VG_Z_LIBC_SONAME, _ZdlPvm, __builtin_delete, DeleteSized ); DELETE_SIZED(SO_SYN_MALLOC, _ZdlPvm, __builtin_delete, DeleteSized ); #endif I also see: 0x00007ffff64c98ac <+876>: call 0x7ffff647c050 <_Znwm@plt> and the same at +1066 and +1685. That matches: // operator new(unsigned long) #if VG_WORDSIZE == 8 ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, _Znwm, __builtin_new); ALLOC_or_BOMB(VG_Z_LIBCXX_SONAME, _Znwm, __builtin_new); ALLOC_or_BOMB(VG_Z_LIBC_SONAME, _Znwm, __builtin_new); ALLOC_or_BOMB(SO_SYN_MALLOC, _Znwm, __builtin_new); #endif With the magic of gdb breakpoints, I see that a breakpoint for std::__new_allocator<vte::property::Registry::Property>::allocate stops here: => 0x00007ffff64c9958 <+1048>: lea (%rax,%rax,2),%rax 0x00007ffff64c995c <+1052>: shl $0x4,%rax 0x00007ffff64c9960 <+1056>: mov %rax,%rdi 0x00007ffff64c9963 <+1059>: mov %rax,-0xc8(%rbp) 0x00007ffff64c996a <+1066>: call 0x7ffff647c050 <_Znwm@plt> where it's about to call operator new (not operator new[]). A breakpoint for std::__new_allocator<vte::property::Registry::Property>::deallocate stops here: => 0x00007ffff64c9b59 <+1561>: mov %rcx,%rdi 0x00007ffff64c9b5c <+1564>: sub %rcx,%rsi 0x00007ffff64c9b5f <+1567>: call 0x7ffff647bf40 <_ZdlPvm@plt> before the call to operator delete. What's especially weird is what I do *not* see: there is no _Znam anywhere in the disassembly, which is very strange because there ought to be, because valgrind's stack trace shows that its operator new[] is being called: ==84== Address 0x1b841470 is 0 bytes inside a block of size 48 alloc'd ==84== at 0x4FE55F3: operator new[](unsigned long) (vg_replace_malloc.c:717) And the gobbledygook for operator new[] on 64-bit Linux is _Znam: // operator new[](unsigned long), #if VG_WORDSIZE == 8 ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, _Znam, __builtin_vec_new ); ALLOC_or_BOMB(VG_Z_LIBCXX_SONAME, _Znam, __builtin_vec_new ); ALLOC_or_BOMB(VG_Z_LIBC_SONAME, _Znam, __builtin_vec_new ); ALLOC_or_BOMB(SO_SYN_MALLOC, _Znam, __builtin_vec_new ); #endif I suppose that's a good thing, because it sure looks like the libstdc++ source code wants operator new, not operator new[]. So the disassembly appears to correspond to the source code, but it does not correspond to what valgrind reports. That's pretty weird! -- You are receiving this mail because: You are watching all bug changes.
