Determine the default for CRYB_LEAKTEST at run-time.

When cryb-test is used as a framework for another project, the compile-time test is useless since cryb-test itself will have been built with coverage disabled.  Besides, it is not a reliable indicator of whether leak detection will work.  Instead, check if the heap is already dirty when we first gain control.
This commit is contained in:
Dag-Erling Smørgrav 2017-05-10 23:45:56 +02:00
parent ea5b521c61
commit 8e0f4a293e
3 changed files with 30 additions and 15 deletions

View file

@ -146,6 +146,7 @@ size_t t_malloc_snapshot(void *, size_t);
#if CRYB_TEST_HAVE_STDIO
void t_malloc_printstats(FILE *);
#endif
unsigned long t_malloc_outstanding(void);
extern struct t_test t_memory_leak;
/*

View file

@ -251,6 +251,16 @@ t_main(t_prepare_func t_prepare, t_cleanup_func t_cleanup,
size_t nt;
int opt;
/*
* Enable memory leak detection by default if and only if the heap
* is empty at the start of main(), since otherwise we have no
* reason to trust that it will be empty after we've run the tests
* and cleaned up what we could.
*/
leaktest = t_malloc_outstanding() ?
t_str_is_true(getenv("CRYB_LEAKTEST")) :
!t_str_is_false(getenv("CRYB_LEAKTEST"));
/* make all unintentional allocation failures fatal */
t_malloc_fatal = 1;
@ -266,13 +276,6 @@ t_main(t_prepare_func t_prepare, t_cleanup_func t_cleanup,
else
t_progname = argv[0];
/* check for leaks, unless doing coverage analysis */
#if CRYB_COVERAGE
leaktest = t_str_is_true(getenv("CRYB_LEAKTEST"));
#else
leaktest = !t_str_is_false(getenv("CRYB_LEAKTEST"));
#endif
/* parse command line options */
while ((opt = getopt(argc, argv, "Llv")) != -1)
switch (opt) {

View file

@ -534,22 +534,33 @@ t_malloc_printstats(FILE *f)
nmapalloc, nmapfree, nmapalloc - nmapfree);
}
/*
* Return number of outstanding allocations
*/
unsigned long
t_malloc_outstanding(void)
{
struct bucket *b;
unsigned int shift;
unsigned long n;
n = nmapalloc - nmapfree;
for (shift = BUCKET_MIN_SHIFT; shift <= BUCKET_MAX_SHIFT; ++shift) {
b = &buckets[shift];
n += b->nalloc - b->nfree;
}
return (n);
}
/*
* Test that fails if we leaked memory
*/
static int
t_malloc_leaked(char **desc, void *arg CRYB_UNUSED)
{
struct bucket *b;
unsigned int shift;
unsigned long nleaked;
nleaked = 0;
for (shift = BUCKET_MIN_SHIFT; shift <= BUCKET_MAX_SHIFT; ++shift) {
b = &buckets[shift];
nleaked += b->nalloc - b->nfree;
}
nleaked += nmapalloc - nmapfree;
nleaked = t_malloc_outstanding();
if (nleaked > 0)
(void)asprintf(desc, "%lu allocation(s) leaked", nleaked);
else