in g++-3.0.4.
</li><br><p>
+ <li><code>--run-libc-freeres=yes</code> [the default]<br>
+ <code>--run-libc-freeres=no</code>
+ <p>The GNU C library (<code>libc.so</code>), which is used by
+ all programs, may allocate memory for its own uses. Usually it
+ doesn't bother to free that memory when the program ends - there
+ would be no point, since the Linux kernel reclaims all process
+ resources when a process exits anyway, so it would just slow
+ things down.
+ <p>
+ The glibc authors realised that this behaviour causes leak checkers, such
+ as Valgrind, to falsely report leaks in glibc, when a leak check
+ is done at exit. In order to avoid this, they provided a
+ routine called <code>__libc_freeres</code> specifically to make
+ glibc release all memory it has allocated. The MemCheck and
+ AddrCheck skins (normal and lightweight valgrinding) therefore
+ try and run <code>__libc_freeres</code> at exit.
+ <p>
+ Unfortunately, in some versions of glibc,
+ <code>__libc_freeres</code> is sufficiently buggy to cause
+ segmentation faults. This is particularly noticeable on Red Hat
+ 7.1. So this flag is provided in order to inhibit the run of
+ <code>__libc_freeres</code>. If your program seems to run fine
+ on valgrind, but segfaults at exit, you may find that
+ <code>--run-libc-freeres=no</code> fixes that, although at the
+ cost of possibly falsely reporting space leaks in
+ <code>libc.so</code>.
+
<li><code>--error-limit=yes</code> [default]<br>
<code>--error-limit=no</code> <p>When enabled, valgrind stops
reporting errors after 30000 in total, or 300 different ones,
from becoming a huge performance overhead in programs with many
errors. </li><br><p>
- <li><code>--cachesim=no</code> [default]<br>
- <code>--cachesim=yes</code> <p>When enabled, turns off memory
- checking, and turns on cache profiling. Cache profiling is
- described in detail in <a href="#cache">Section 7</a>.
- </li><br><p>
-
<li><code>--weird-hacks=hack1,hack2,...</code>
Pass miscellaneous hints to Valgrind which slightly modify the
simulated behaviour in nonstandard or dangerous ways, possibly
{
int res;
extern void __libc_freeres(void);
- //__libc_freeres();
+ __libc_freeres();
VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
VG_USERREQ__LIBC_FREERES_DONE, 0, 0, 0, 0);
/*NOTREACHED*/
extern Int VG_(clo_backtrace_size);
/* Engage miscellaneous wierd hacks needed for some progs. */
extern Char* VG_(clo_weird_hacks);
+/* Should we run __libc_freeres at exit? Sometimes causes crashes.
+ Default: YES. Note this is subservient to VG_(needs).libc_freeres;
+ if the latter says False, then the setting of VG_(clo_weird_hacks)
+ is ignored. Ie if a skin says no, I don't want this to run, that
+ cannot be overridden from the command line. */
+extern Bool VG_(clo_run_libc_freeres);
/* ---------------------------------------------------------------------
Int VG_(clo_dump_error) = 0;
Int VG_(clo_backtrace_size) = 4;
Char* VG_(clo_weird_hacks) = NULL;
+Bool VG_(clo_run_libc_freeres) = True;
/* This Bool is needed by wrappers in vg_clientmalloc.c to decide how
to behave. Initially we say False. */
" --sloppy-malloc=no|yes round malloc sizes to next word? [no]\n"
" --alignment=<number> set minimum alignment of allocations [4]\n"
" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
+" --run-libc-freeres=no|yes Free up glibc memory at exit? [yes]\n"
" --logfile-fd=<number> file descriptor for messages [2=stderr]\n"
" --suppressions=<filename> suppress errors described in\n"
" suppressions file <filename>\n"
else if (STREQ(argv[i], "--trace-children=no"))
VG_(clo_trace_children) = False;
+ else if (STREQ(argv[i], "--run-libc-freeres=yes"))
+ VG_(clo_run_libc_freeres) = True;
+ else if (STREQ(argv[i], "--run-libc-freeres=no"))
+ VG_(clo_run_libc_freeres) = False;
+
else if (STREQN(15, argv[i], "--sanity-level="))
VG_(sanity_level) = (Int)VG_(atoll)(&argv[i][15]);
__libc_freeres does some invalid frees which crash
the unprotected malloc/free system. */
- /* If __NR_exit, remember the supplied argument. */
- if (VG_(threads)[tid].m_eax == __NR_exit)
+ if (VG_(threads)[tid].m_eax == __NR_exit) {
+
+ /* If __NR_exit, remember the supplied argument. */
VG_(exitcode) = VG_(threads)[tid].m_ebx; /* syscall arg1 */
- if (VG_(threads)[tid].m_eax == __NR_exit
- && ! VG_(needs).libc_freeres) {
- if (VG_(clo_trace_syscalls) || VG_(clo_trace_sched)) {
- VG_(message)(Vg_DebugMsg,
- "Caught __NR_exit; quitting");
- }
- return VgSrc_ExitSyscall;
- }
+ /* Only run __libc_freeres if the skin says it's ok and
+ it hasn't been overridden with --run-libc-freeres=no
+ on the command line. */
+
+ if (VG_(needs).libc_freeres && VG_(clo_run_libc_freeres)) {
+
+ if (VG_(clo_verbosity) >= 2
+ || VG_(clo_trace_syscalls) || VG_(clo_trace_sched)) {
+ VG_(message)(Vg_DebugMsg,
+ "Caught __NR_exit; running __libc_freeres()");
+ }
+ VG_(nuke_all_threads_except) ( tid );
+ VG_(threads)[tid].m_eip = (UInt)(&VG_(__libc_freeres_wrapper));
+ vg_assert(VG_(threads)[tid].status == VgTs_Runnable);
+ goto stage1; /* party on, dudes (but not for much longer :) */
+
+ } else {
+ /* We won't run __libc_freeres; just exit now. */
+ if (VG_(clo_verbosity) >= 2
+ || VG_(clo_trace_syscalls) || VG_(clo_trace_sched)) {
+ VG_(message)(Vg_DebugMsg,
+ "Caught __NR_exit; quitting");
+ }
+ return VgSrc_ExitSyscall;
+ }
- if (VG_(threads)[tid].m_eax == __NR_exit) {
- vg_assert(VG_(needs).libc_freeres);
- if (0 || VG_(clo_trace_syscalls) || VG_(clo_trace_sched)) {
- VG_(message)(Vg_DebugMsg,
- "Caught __NR_exit; running __libc_freeres()");
- }
- VG_(nuke_all_threads_except) ( tid );
- VG_(threads)[tid].m_eip = (UInt)(&VG_(__libc_freeres_wrapper));
- vg_assert(VG_(threads)[tid].status == VgTs_Runnable);
- goto stage1; /* party on, dudes (but not for much longer :) */
}
+ /* We've dealt with __NR_exit at this point. */
+ vg_assert(VG_(threads)[tid].m_eax != __NR_exit);
+
/* Trap syscalls to __NR_sched_yield and just have this
thread yield instead. Not essential, just an
optimisation. */