Minor mods to stop make the leak detector behave properly for the
following kind of stupid test program
int main (void) { char* a = malloc(100); return 0; }
which many people seem fond of trying for some reason.
In general the leak detector works fine.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@387 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/vg_include.h b/coregrind/vg_include.h
index ec923b1..9474b60 100644
--- a/coregrind/vg_include.h
+++ b/coregrind/vg_include.h
@@ -915,7 +915,7 @@
__attribute__ ((__noreturn__));
/* Get memory by anonymous mmap. */
-extern void* VG_(get_memory_from_mmap) ( Int nBytes );
+extern void* VG_(get_memory_from_mmap) ( Int nBytes, Char* who );
/* Crude stand-in for the glibc system() call. */
extern Int VG_(system) ( Char* cmd );
diff --git a/coregrind/vg_malloc2.c b/coregrind/vg_malloc2.c
index ab87bdb..87f580d 100644
--- a/coregrind/vg_malloc2.c
+++ b/coregrind/vg_malloc2.c
@@ -233,7 +233,8 @@
cszW += 2; /* Take into account sb->next and sb->n_words fields */
if (cszW < a->min_sblockW) cszW = a->min_sblockW;
while ((cszW % VKI_WORDS_PER_PAGE) > 0) cszW++;
- sb = VG_(get_memory_from_mmap) ( cszW * sizeof(Word) );
+ sb = VG_(get_memory_from_mmap) ( cszW * sizeof(Word),
+ "newSuperblock" );
sb->n_payload_words = cszW - 2;
a->bytes_mmaped += cszW * sizeof(Word);
if (0)
diff --git a/coregrind/vg_memory.c b/coregrind/vg_memory.c
index cd8eba1..4b4fe0c 100644
--- a/coregrind/vg_memory.c
+++ b/coregrind/vg_memory.c
@@ -332,7 +332,7 @@
although this isn't important, so the following assert is
spurious. */
vg_assert(0 == (sizeof(SecMap) % VKI_BYTES_PER_PAGE));
- map = VG_(get_memory_from_mmap)( sizeof(SecMap) );
+ map = VG_(get_memory_from_mmap)( sizeof(SecMap), caller );
for (i = 0; i < 8192; i++)
map->abits[i] = VGM_BYTE_INVALID; /* Invalid address */
@@ -1963,8 +1963,40 @@
static
void vg_detect_memory_leaks_notify_addr ( Addr a, UInt word_at_a )
{
- Int sh_no;
- Addr ptr = (Addr)word_at_a;
+ Int sh_no;
+ Addr ptr;
+
+ /* Rule out some known causes of bogus pointers. Mostly these do
+ not cause much trouble because only a few false pointers can
+ ever lurk in these places. This mainly stops it reporting that
+ blocks are still reachable in stupid test programs like this
+
+ int main (void) { char* a = malloc(100); return 0; }
+
+ which people seem inordinately fond of writing, for some reason.
+
+ Note that this is a complete kludge. It would be better to
+ ignore any addresses corresponding to valgrind.so's .bss and
+ .data segments, but I cannot think of a reliable way to identify
+ where the .bss segment has been put. If you can, drop me a
+ line.
+ */
+ if (a >= ((Addr)(&VG_(stack)))
+ && a <= ((Addr)(&VG_(stack))) + sizeof(VG_(stack))) {
+ return;
+ }
+ if (a >= ((Addr)(&VG_(m_state_static)))
+ && a <= ((Addr)(&VG_(m_state_static))) + sizeof(VG_(m_state_static))) {
+ return;
+ }
+ if (a == (Addr)(&vglc_min_mallocd_addr))
+ return;
+ if (a == (Addr)(&vglc_max_mallocd_addr))
+ return;
+
+ /* OK, let's get on and do something Useful for a change. */
+
+ ptr = (Addr)word_at_a;
if (ptr >= vglc_min_mallocd_addr && ptr <= vglc_max_mallocd_addr) {
/* Might be legitimate; we'll have to investigate further. */
sh_no = find_shadow_for ( ptr, vglc_shadows, vglc_n_shadows );
@@ -1975,6 +2007,7 @@
+ vglc_shadows[sh_no]->size);
/* Decide whether Proper-ly or Interior-ly reached. */
if (ptr == vglc_shadows[sh_no]->data) {
+ if (0) VG_(printf)("pointer at %p to %p\n", a, word_at_a );
vglc_reachedness[sh_no] = Proper;
} else {
if (vglc_reachedness[sh_no] == Unreached)
@@ -2147,10 +2180,10 @@
VG_(message)(Vg_UserMsg, "");
VG_(message)(Vg_UserMsg, "LEAK SUMMARY:");
- VG_(message)(Vg_UserMsg, " possibly lost: %d bytes in %d blocks.",
- bytes_dubious, blocks_dubious );
VG_(message)(Vg_UserMsg, " definitely lost: %d bytes in %d blocks.",
bytes_leaked, blocks_leaked );
+ VG_(message)(Vg_UserMsg, " possibly lost: %d bytes in %d blocks.",
+ bytes_dubious, blocks_dubious );
VG_(message)(Vg_UserMsg, " still reachable: %d bytes in %d blocks.",
bytes_reachable, blocks_reachable );
if (!VG_(clo_show_reachable)) {
diff --git a/coregrind/vg_mylibc.c b/coregrind/vg_mylibc.c
index b2b62b4..4f8cb71 100644
--- a/coregrind/vg_mylibc.c
+++ b/coregrind/vg_mylibc.c
@@ -1241,7 +1241,7 @@
Primitive support for bagging memory via mmap.
------------------------------------------------------------------ */
-void* VG_(get_memory_from_mmap) ( Int nBytes )
+void* VG_(get_memory_from_mmap) ( Int nBytes, Char* who )
{
static UInt tot_alloc = 0;
void* p = VG_(mmap)( 0, nBytes,
@@ -1250,8 +1250,9 @@
if (p != ((void*)(-1))) {
tot_alloc += (UInt)nBytes;
if (0)
- VG_(printf)("get_memory_from_mmap: %d tot, %d req\n",
- tot_alloc, nBytes);
+ VG_(printf)(
+ "get_memory_from_mmap: %d tot, %d req = %p .. %p, caller %s\n",
+ tot_alloc, nBytes, p, ((char*)p) + nBytes - 1, who );
return p;
}
VG_(printf)("vg_get_memory_from_mmap failed on request of %d\n",
diff --git a/coregrind/vg_scheduler.c b/coregrind/vg_scheduler.c
index 65a5196..4e68b67 100644
--- a/coregrind/vg_scheduler.c
+++ b/coregrind/vg_scheduler.c
@@ -2116,7 +2116,8 @@
assigning it for the first time. */
vg_assert(VG_(threads)[tid].stack_size == 0);
vg_assert(VG_(threads)[tid].stack_base == (Addr)NULL);
- new_stack = (Addr)VG_(get_memory_from_mmap)( new_stk_szb );
+ new_stack = (Addr)VG_(get_memory_from_mmap)( new_stk_szb,
+ "new thread stack" );
VG_(threads)[tid].stack_base = new_stack;
VG_(threads)[tid].stack_size = new_stk_szb;
VG_(threads)[tid].stack_highest_word
diff --git a/coregrind/vg_transtab.c b/coregrind/vg_transtab.c
index a364df0..e69dda2 100644
--- a/coregrind/vg_transtab.c
+++ b/coregrind/vg_transtab.c
@@ -508,11 +508,13 @@
/* Allocate the translation table and translation cache. */
vg_assert(vg_tc == NULL);
- vg_tc = VG_(get_memory_from_mmap) ( VG_TC_SIZE * sizeof(UChar) );
+ vg_tc = VG_(get_memory_from_mmap) ( VG_TC_SIZE * sizeof(UChar),
+ "trans-cache" );
vg_assert(vg_tc != NULL);
vg_assert(vg_tt == NULL);
- vg_tt = VG_(get_memory_from_mmap) ( VG_TT_SIZE * sizeof(TTEntry) );
+ vg_tt = VG_(get_memory_from_mmap) ( VG_TT_SIZE * sizeof(TTEntry),
+ "trans-table" );
vg_assert(vg_tt != NULL);
/* The main translation table is empty. */
diff --git a/tests/Makefile.am b/tests/Makefile.am
index d68b430..f873b9f 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -30,4 +30,4 @@
pth_once.c weirdioctl.c pth_signal1.c pth_signal2.c \
discard.c pth_semaphore1.c new_override.cpp pth_yield.c \
sigaltstack.c erringfds.c sigwait_all.c \
- pth_cancel1.c pth_cancel2.c pth_signal_gober.c
+ pth_cancel1.c pth_cancel2.c pth_signal_gober.c nanoleak.c
diff --git a/tests/nanoleak.c b/tests/nanoleak.c
new file mode 100644
index 0000000..2b7121c
--- /dev/null
+++ b/tests/nanoleak.c
@@ -0,0 +1,9 @@
+
+#include <malloc.h>
+
+int main ( void )
+{
+ volatile int* a = malloc(1000);
+ a[0] = 0;
+ return a[0];
+}
diff --git a/vg_include.h b/vg_include.h
index ec923b1..9474b60 100644
--- a/vg_include.h
+++ b/vg_include.h
@@ -915,7 +915,7 @@
__attribute__ ((__noreturn__));
/* Get memory by anonymous mmap. */
-extern void* VG_(get_memory_from_mmap) ( Int nBytes );
+extern void* VG_(get_memory_from_mmap) ( Int nBytes, Char* who );
/* Crude stand-in for the glibc system() call. */
extern Int VG_(system) ( Char* cmd );
diff --git a/vg_malloc2.c b/vg_malloc2.c
index ab87bdb..87f580d 100644
--- a/vg_malloc2.c
+++ b/vg_malloc2.c
@@ -233,7 +233,8 @@
cszW += 2; /* Take into account sb->next and sb->n_words fields */
if (cszW < a->min_sblockW) cszW = a->min_sblockW;
while ((cszW % VKI_WORDS_PER_PAGE) > 0) cszW++;
- sb = VG_(get_memory_from_mmap) ( cszW * sizeof(Word) );
+ sb = VG_(get_memory_from_mmap) ( cszW * sizeof(Word),
+ "newSuperblock" );
sb->n_payload_words = cszW - 2;
a->bytes_mmaped += cszW * sizeof(Word);
if (0)
diff --git a/vg_memory.c b/vg_memory.c
index cd8eba1..4b4fe0c 100644
--- a/vg_memory.c
+++ b/vg_memory.c
@@ -332,7 +332,7 @@
although this isn't important, so the following assert is
spurious. */
vg_assert(0 == (sizeof(SecMap) % VKI_BYTES_PER_PAGE));
- map = VG_(get_memory_from_mmap)( sizeof(SecMap) );
+ map = VG_(get_memory_from_mmap)( sizeof(SecMap), caller );
for (i = 0; i < 8192; i++)
map->abits[i] = VGM_BYTE_INVALID; /* Invalid address */
@@ -1963,8 +1963,40 @@
static
void vg_detect_memory_leaks_notify_addr ( Addr a, UInt word_at_a )
{
- Int sh_no;
- Addr ptr = (Addr)word_at_a;
+ Int sh_no;
+ Addr ptr;
+
+ /* Rule out some known causes of bogus pointers. Mostly these do
+ not cause much trouble because only a few false pointers can
+ ever lurk in these places. This mainly stops it reporting that
+ blocks are still reachable in stupid test programs like this
+
+ int main (void) { char* a = malloc(100); return 0; }
+
+ which people seem inordinately fond of writing, for some reason.
+
+ Note that this is a complete kludge. It would be better to
+ ignore any addresses corresponding to valgrind.so's .bss and
+ .data segments, but I cannot think of a reliable way to identify
+ where the .bss segment has been put. If you can, drop me a
+ line.
+ */
+ if (a >= ((Addr)(&VG_(stack)))
+ && a <= ((Addr)(&VG_(stack))) + sizeof(VG_(stack))) {
+ return;
+ }
+ if (a >= ((Addr)(&VG_(m_state_static)))
+ && a <= ((Addr)(&VG_(m_state_static))) + sizeof(VG_(m_state_static))) {
+ return;
+ }
+ if (a == (Addr)(&vglc_min_mallocd_addr))
+ return;
+ if (a == (Addr)(&vglc_max_mallocd_addr))
+ return;
+
+ /* OK, let's get on and do something Useful for a change. */
+
+ ptr = (Addr)word_at_a;
if (ptr >= vglc_min_mallocd_addr && ptr <= vglc_max_mallocd_addr) {
/* Might be legitimate; we'll have to investigate further. */
sh_no = find_shadow_for ( ptr, vglc_shadows, vglc_n_shadows );
@@ -1975,6 +2007,7 @@
+ vglc_shadows[sh_no]->size);
/* Decide whether Proper-ly or Interior-ly reached. */
if (ptr == vglc_shadows[sh_no]->data) {
+ if (0) VG_(printf)("pointer at %p to %p\n", a, word_at_a );
vglc_reachedness[sh_no] = Proper;
} else {
if (vglc_reachedness[sh_no] == Unreached)
@@ -2147,10 +2180,10 @@
VG_(message)(Vg_UserMsg, "");
VG_(message)(Vg_UserMsg, "LEAK SUMMARY:");
- VG_(message)(Vg_UserMsg, " possibly lost: %d bytes in %d blocks.",
- bytes_dubious, blocks_dubious );
VG_(message)(Vg_UserMsg, " definitely lost: %d bytes in %d blocks.",
bytes_leaked, blocks_leaked );
+ VG_(message)(Vg_UserMsg, " possibly lost: %d bytes in %d blocks.",
+ bytes_dubious, blocks_dubious );
VG_(message)(Vg_UserMsg, " still reachable: %d bytes in %d blocks.",
bytes_reachable, blocks_reachable );
if (!VG_(clo_show_reachable)) {
diff --git a/vg_mylibc.c b/vg_mylibc.c
index b2b62b4..4f8cb71 100644
--- a/vg_mylibc.c
+++ b/vg_mylibc.c
@@ -1241,7 +1241,7 @@
Primitive support for bagging memory via mmap.
------------------------------------------------------------------ */
-void* VG_(get_memory_from_mmap) ( Int nBytes )
+void* VG_(get_memory_from_mmap) ( Int nBytes, Char* who )
{
static UInt tot_alloc = 0;
void* p = VG_(mmap)( 0, nBytes,
@@ -1250,8 +1250,9 @@
if (p != ((void*)(-1))) {
tot_alloc += (UInt)nBytes;
if (0)
- VG_(printf)("get_memory_from_mmap: %d tot, %d req\n",
- tot_alloc, nBytes);
+ VG_(printf)(
+ "get_memory_from_mmap: %d tot, %d req = %p .. %p, caller %s\n",
+ tot_alloc, nBytes, p, ((char*)p) + nBytes - 1, who );
return p;
}
VG_(printf)("vg_get_memory_from_mmap failed on request of %d\n",
diff --git a/vg_scheduler.c b/vg_scheduler.c
index 65a5196..4e68b67 100644
--- a/vg_scheduler.c
+++ b/vg_scheduler.c
@@ -2116,7 +2116,8 @@
assigning it for the first time. */
vg_assert(VG_(threads)[tid].stack_size == 0);
vg_assert(VG_(threads)[tid].stack_base == (Addr)NULL);
- new_stack = (Addr)VG_(get_memory_from_mmap)( new_stk_szb );
+ new_stack = (Addr)VG_(get_memory_from_mmap)( new_stk_szb,
+ "new thread stack" );
VG_(threads)[tid].stack_base = new_stack;
VG_(threads)[tid].stack_size = new_stk_szb;
VG_(threads)[tid].stack_highest_word
diff --git a/vg_transtab.c b/vg_transtab.c
index a364df0..e69dda2 100644
--- a/vg_transtab.c
+++ b/vg_transtab.c
@@ -508,11 +508,13 @@
/* Allocate the translation table and translation cache. */
vg_assert(vg_tc == NULL);
- vg_tc = VG_(get_memory_from_mmap) ( VG_TC_SIZE * sizeof(UChar) );
+ vg_tc = VG_(get_memory_from_mmap) ( VG_TC_SIZE * sizeof(UChar),
+ "trans-cache" );
vg_assert(vg_tc != NULL);
vg_assert(vg_tt == NULL);
- vg_tt = VG_(get_memory_from_mmap) ( VG_TT_SIZE * sizeof(TTEntry) );
+ vg_tt = VG_(get_memory_from_mmap) ( VG_TT_SIZE * sizeof(TTEntry),
+ "trans-table" );
vg_assert(vg_tt != NULL);
/* The main translation table is empty. */