From owner-freebsd-stable@FreeBSD.ORG Sun Jan 20 12:28:01 2013 Return-Path: Delivered-To: freebsd-stable@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id 42770A23; Sun, 20 Jan 2013 12:28:01 +0000 (UTC) (envelope-from to.my.trociny@gmail.com) Received: from mail-ee0-f47.google.com (mail-ee0-f47.google.com [74.125.83.47]) by mx1.freebsd.org (Postfix) with ESMTP id A93E4F07; Sun, 20 Jan 2013 12:28:00 +0000 (UTC) Received: by mail-ee0-f47.google.com with SMTP id e52so2403474eek.20 for ; Sun, 20 Jan 2013 04:27:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:sender:date:from:to:cc:subject:message-id:mime-version :content-type:content-disposition:user-agent; bh=4J2T/XicdmMgSmAvcFkbrMv5htRiqNzyKnj02VVgWGs=; b=P82oWSxhn78jlsLPxluYbyUFlgsfuijRzsy7yk6tQW8FMZ66VafRJ1KjDcoOzYhjBo duRRwpY0/Sj9mtwr5HnT7hoO6Us22IOaNS8KBjb7chuD58ftaLnUBGQs+0AOt31m+esH YV2BnYX//JLJnN9dsm4lemXli+QQZJyM/LFYpuafPH9wrVduMHa0xz8UPMkSdNBfLCoU zyM00VWJ2/G8a8G0MQoD2q9gq9JOtD+iM9pW/+nFiBkkuhEiBy2qpfotWcop7emI7FrM fNUNGKIbpLiOwBNH6M/MYh5+p3T8y666XAweBPeUNxmWkf5qjP3sxfNRoafsVXHQyLVt GpJA== X-Received: by 10.14.175.70 with SMTP id y46mr48309121eel.6.1358684398459; Sun, 20 Jan 2013 04:19:58 -0800 (PST) Received: from localhost ([178.150.115.244]) by mx.google.com with ESMTPS id 46sm17070663eeg.4.2013.01.20.04.19.56 (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Sun, 20 Jan 2013 04:19:57 -0800 (PST) Sender: Mikolaj Golub Date: Sun, 20 Jan 2013 14:19:55 +0200 From: Mikolaj Golub To: freebsd-stable@freebsd.org Subject: libstdc++, libsupc++, delete operators and valgrind Message-ID: <20130120121954.GA4634@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) Cc: Stanislav Sedov X-BeenThere: freebsd-stable@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Production branch of FreeBSD source code List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 20 Jan 2013 12:28:01 -0000 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? -- Mikolaj Golub