valgrind memcheck shows leaks in svn clang compile of simplest c++ program

Is using valgrind memcheck a good way to detect memory leaks in clang?
If so, then the following memcheck run output may be useful.

The OS:

Linux evansl-desktop 2.6.32-41-generic #90-Ubuntu SMP Tue May 22 11:29:51 UTC 2012 x86_64 GNU/Linux

The program:

//Do nothing (No OPeration) benchmark.
int main()
{
  return 0;
}

the compiler:

clang version 3.3 (trunk 171246) (llvm/trunk 171244)
Target: x86_64-unknown-linux-gnu
Thread model: posix

the compiler configuration:

#!/bin/bash
this_dir=`pwd`
ls $this_dir/../../../llvm.src/configure
$this_dir/../../../llvm.src/configure \
  --prefix=$this_dir/../install \
  --enable-optimized=NO \
  --enable-assertions=YES \
  --enable-debug-runtime=YES \
  --enable-debug-symbols=YES \
  #

the memcheck output:

==5556== Memcheck, a memory error detector
==5556== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==5556== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==5556== Command: /home/evansl/download/llvm/svn/top/out/debug/install/bin/clang -cc1 -triple x86_64-unknown-linux-gnu -emit-obj -mrelax-all -disable-free -disable-llvm-verifier -main-file-name tuple.benchmark.nop.cpp -mrelocation-model static -mdisable-fp-elim -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-linker-version 2.20.1 -momit-leaf-frame-pointer -coverage-file /home/evansl/prog_dev/boost-svn/ro/boost_1_49_0/sandbox/rw/variadic_templates/sandbox/slim/test.work/tuple.benchmark.nop.o -resource-dir /home/evansl/download/llvm/svn/top/out/debug/install/bin/../lib/clang/3.3 -D TUPLE_IMPL=bcon12_horizontal -D TUPLE_SIZE=10 -D TUPLE_UNROLL_MAX=-1 -D TREE_DEPTH=2 -D TUPLE_TEMPLATED_CTOR=1 -I /home/evansl/prog_dev/boost-svn/ro/boost_1_49_0 -fmodule-cache-path /var/tmp/clang-module-cache -internal-isystem /usr/lib64/gcc/x86_64-linux-gnu/4.4/../../../../include/c++/4.4 -internal-isystem /usr/lib64/gcc/x86_64-linux-gnu/4.4/../../../.!

./include/
c++/4.4/x86_64-linux-gnu -internal-isystem /usr/lib64/gcc/x86_64-linux-gnu/4.4/../../../../include/c++/4.4/backward -internal-isystem /usr/local/include -internal-isystem /home/evansl/download/llvm/svn/top/out/debug/install/bin/../lib/clang/3.3/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /home/evansl/prog_dev/boost-svn/ro/boost_1_49_0/sandbox/rw/variadic_templates/sandbox/slim/test.work -ferror-limit 19 -fmessage-length 0 -mstackrealign -fobjc-runtime=gcc -fcxx-exceptions -fexceptions -fdiagnostics-show-option -backend-option -vectorize-loops -o tuple.benchmark.nop.o -x c++ tuple.benchmark.nop.cpp

For those whose mail reader choked on this (as did gmail for me), the same report is also attached.

– Matthieu

clang_leak.txt (359 KB)

Is using valgrind memcheck a good way to detect memory leaks in clang?

No. Look at this part of the command line:

==5556== Command: /home/evansl/download/llvm/svn/top/out/debug/install/bin/clang -cc1 -disable-free

This option (passed by default from the driver to the main compiler) instructs Clang not to free any of the AST nodes it allocates, to save time on process shutdown. So obviously they all leak.

Sebastian

Is there an -enable-free flag to the driver that stops these leaks?
(The `clang -help` shows none, but maybe it's hidden like the ### flag).
Grepping the sources shows:

  CmdArgs.push_back("-disable-free");
8373719 224 -rw-r--r-- 1 evansl evansl 221926 Dec 29 19:36
./Driver/Tools.cpp

but Tools.cpp looks like that's hardcoded (IOW, it's not guarded by
some test that looks like a check of the input args).

-Larry

I managed to change to args to the main compiler so that -disable-free
no longer appears in the memcheck output:

==13487== Memcheck, a memory error detector
==13487== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==13487== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for
copyright info
==13487== Command:
/home/evansl/download/llvm/svn/top/out/debug/install/bin/clang -cc1
-triple x86_64-unknown-linux-gnu -emit-obj -mrelax-all
-disable-llvm-verifier -main-file-name tuple.benchmark.nop.cpp
-mrelocation-model static -mdisable-fp-elim -fmath-errno -masm-verbose
-mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu
x86-64 -target-linker-version 2.20.1 -momit-leaf-frame-pointer
-coverage-file
/home/evansl/prog_dev/boost-svn/ro/boost_1_49_0/sandbox/rw/variadic_templates/sandbox/slim/test.work/tuple.benchmark.nop.o
-resource-dir
/home/evansl/download/llvm/svn/top/out/debug/install/bin/../lib/clang/3.3 -D
TUPLE_IMPL=bcon12_horizontal -D TUPLE_SIZE=10 -D TUPLE_UNROLL_MAX=-1 -D
TREE_DEPTH=2 -D TUPLE_TEMPLATED_CTOR=1 -I
/home/evansl/prog_dev/boost-svn/ro/boost_1_49_0 -fmodule-cache-path
/var/tmp/clang-module-cache -internal-isystem
/home/evansl/download/gcc/4.8-20121028/install/lib/gcc/x86_64-unknown-linux-gnu/4.8.0/../../../../include/c++/4.8.0
-internal-isystem
/home/evansl/download/gcc/4.8-20121028/install/lib/gcc/x86_64-unknown-linux-gnu/4.8.0/../../../../include/c++/4.8.0/x86_64-unknown-linux-gnu
-internal-isystem
/home/evansl/download/gcc/4.8-20121028/install/lib/gcc/x86_64-unknown-linux-gnu/4.8.0/../../../../include/c++/4.8.0/backward
-internal-isystem /usr/local/include -internal-isystem
/home/evansl/download/llvm/svn/top/out/debug/install/bin/../lib/clang/3.3/include
-internal-externc-isystem /usr/include/x86_64-linux-gnu
-internal-externc-isystem /include -internal-externc-isystem
/usr/include -std=c++11 -fdeprecated-macro -fdebug-compilation-dir
/home/evansl/prog_dev/boost-svn/ro/boost_1_49_0/sandbox/rw/variadic_templates/sandbox/slim/test.work
-ferror-limit 19 -fmessage-length 0 -mstackrealign -fobjc-runtime=gcc
-fcxx-exceptions -fexceptions -fdiagnostics-show-option -backend-option
-vectorize-loops -o tuple.benchmark.nop.o -x c++ tuple.benchmark.nop.cpp
==13487==
--13487-- Valgrind options:
--13487-- --suppressions=/usr/lib/valgrind/debian-libc6-dbg.supp
--13487-- --tool=memcheck
--13487-- -v
--13487-- --leak-check=full
--13487-- --show-reachable=yes
--13487-- Contents of /proc/version:
--13487-- Linux version 2.6.32-41-generic (buildd@yellow) (gcc version
4.4.3 (Ubuntu 4.4.3-4ubuntu5.1) ) #90-Ubuntu SMP Tue May 22 11:29:51 UTC
2012
--13487-- Arch and hwcaps: AMD64, amd64-sse3-cx16
--13487-- Page sizes: currently 4096, max supported 4096
--13487-- Valgrind library directory: /usr/lib/valgrind
--13487-- Reading syms from
/home/evansl/download/llvm/svn/top/out/debug/install/bin/clang (0x400000)
--13487-- Reading syms from /lib/ld-2.11.1.so (0x4000000)
--13487-- Reading debug info from /lib/ld-2.11.1.so ..
--13487-- .. CRC mismatch (computed d6b02b0b wanted 324d1273)
--13487-- Reading debug info from /usr/lib/debug/lib/ld-2.11.1.so ..
--13487-- Reading syms from /usr/lib/valgrind/memcheck-amd64-linux
(0x38000000)
--13487-- object doesn't have a dynamic symbol table
--13487-- Reading suppressions file: /usr/lib/valgrind/debian-libc6-dbg.supp
--13487-- Reading suppressions file: /usr/lib/valgrind/default.supp
--13487-- REDIR: 0x4018390 (strlen) redirected to 0x380402d7
(vgPlain_amd64_linux_REDIR_FOR_strlen)
--13487-- Reading syms from
/usr/lib/valgrind/vgpreload_core-amd64-linux.so (0x4a22000)
--13487-- Reading syms from
/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so (0x4c24000)
==13487== WARNING: new redirection conflicts with existing -- ignoring it
--13487-- new: 0x04018390 (strlen ) R-> 0x04c28710 strlen
--13487-- REDIR: 0x4018200 (index) redirected to 0x4c28320 (index)
--13487-- REDIR: 0x4018280 (strcmp) redirected to 0x4c28cf0 (strcmp)
--13487-- Reading syms from /lib/libpthread-2.11.1.so (0x4e2d000)
--13487-- Reading debug info from /lib/libpthread-2.11.1.so ..
--13487-- .. CRC mismatch (computed d460a184 wanted 81aea168)
.
.
.

However, there's still a fair sized leak:

.
.
.
==13487== 75,924 (20,784 direct, 55,140 indirect) bytes in 1 blocks are
definitely lost in loss record 38 of 38
==13487== at 0x4C27CC1: operator new(unsigned long)
(vg_replace_malloc.c:261)
==13487== by 0x16E43C6:
llvm::RegisterTargetMachine<llvm::X86_64TargetMachine>::Allocator(llvm::Target
const&, llvm::StringRef, llvm::StringRef, llvm::StringRef,
llvm::TargetOptions const&, llvm::Reloc::Model, llvm::CodeModel::Model,
llvm::CodeGenOpt::Level) (TargetRegistry.h:1015)
==13487== by 0x7F43F2: (anonymous
namespace)::EmitAssemblyHelper::CreateTargetMachine(bool)
(TargetRegistry.h:340)
==13487== by 0x7F4C90: (anonymous
namespace)::EmitAssemblyHelper::EmitAssembly(clang::BackendAction,
llvm::raw_ostream*) (BackendUtil.cpp:521)
==13487== by 0x7F5ED4:
clang::EmitBackendOutput(clang::DiagnosticsEngine&,
clang::CodeGenOptions const&, clang::TargetOptions const&,
clang::LangOptions const&, llvm::Module*, clang::BackendAction,
llvm::raw_ostream*) (BackendUtil.cpp:579)
==13487== by 0x7F2C9B:
clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&)
(CodeGenAction.cpp:162)
==13487== by 0x94D55D: clang::ParseAST(clang::Sema&, bool, bool)
(ParseAST.cpp:142)
==13487== by 0x7F1B32: clang::CodeGenAction::ExecuteAction()
(CodeGenAction.cpp:423)
==13487== by 0x689E80: clang::FrontendAction::Execute()
(FrontendAction.cpp:381)
==13487== by 0x667AD4:
clang::CompilerInstance::ExecuteAction(clang::FrontendAction&)
(CompilerInstance.cpp:703)
==13487== by 0x652093:
clang::ExecuteCompilerInvocation(clang::CompilerInstance*)
(ExecuteCompilerInvocation.cpp:234)
==13487== by 0x649DAF: cc1_main(char const**, char const**, char
const*, void*) (cc1_main.cpp:98)
==13487==
==13487== LEAK SUMMARY:
==13487== definitely lost: 20,784 bytes in 1 blocks
==13487== indirectly lost: 55,140 bytes in 40 blocks
==13487== possibly lost: 55 bytes in 1 blocks
==13487== still reachable: 120 bytes in 4 blocks
==13487== suppressed: 0 bytes in 0 blocks
==13487==
==13487== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 4 from 4)
--13487--
--13487-- used_suppression: 2 dl-hack3-cond-1
--13487-- used_suppression: 2 glibc-2.5.x-on-SUSE-10.2-(PPC)-2a
==13487==
==13487== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 4 from 4)

HTH.

-regards,
Larry

Could you file a bug? It would be very reasonable for clang to delete
the TargetMachine after it's done with it when -disable-free isn't passed.

John.

[snip]

Could you file a bug? It would be very reasonable for clang to delete
the TargetMachine after it's done with it when -disable-free isn't passed.

John.

OK. It's here:

http://llvm.org/bugs/show_bug.cgi?id=14808