Index: cackey.c ================================================================== --- cackey.c +++ cackey.c @@ -157,38 +157,50 @@ #ifdef CACKEY_DEBUG # ifdef HAVE_STDIO_H # include # endif -# define CACKEY_DEBUG_PRINTF(x...) { fprintf(stderr, "%s(): ", __func__); fprintf(stderr, x); fprintf(stderr, "\n"); } -# define CACKEY_DEBUG_PRINTBUF(f, x, y) { unsigned char *TMPBUF; unsigned long idx; TMPBUF = (unsigned char *) (x); fprintf(stderr, "%s(): %s (%s/%lu = {%02x", __func__, f, #x, (unsigned long) (y), TMPBUF[0]); for (idx = 1; idx < (y); idx++) { fprintf(stderr, ", %02x", TMPBUF[idx]); }; fprintf(stderr, "})\n"); } -# define CACKEY_DEBUG_PERROR(x) { fprintf(stderr, "%s(): ", __func__); perror(x); } +# define CACKEY_DEBUG_PRINTF(x...) { fprintf(stderr, "%s():%i: ", __func__, __LINE__); fprintf(stderr, x); fprintf(stderr, "\n"); } +# define CACKEY_DEBUG_PRINTBUF(f, x, y) { unsigned char *TMPBUF; unsigned long idx; TMPBUF = (unsigned char *) (x); fprintf(stderr, "%s():%i: %s (%s/%lu = {%02x", __func__, __LINE__, f, #x, (unsigned long) (y), TMPBUF[0]); for (idx = 1; idx < (y); idx++) { fprintf(stderr, ", %02x", TMPBUF[idx]); }; fprintf(stderr, "})\n"); } +# define CACKEY_DEBUG_PERROR(x) { fprintf(stderr, "%s():%i: ", __func__, __LINE__); perror(x); } # define free(x) { CACKEY_DEBUG_PRINTF("FREE(%p) (%s)", x, #x); free(x); } -static void *CACKEY_DEBUG_FUNC_MALLOC(size_t size, const char *func) { +static void *CACKEY_DEBUG_FUNC_MALLOC(size_t size, const char *func, int line) { void *retval; retval = malloc(size); - fprintf(stderr, "%s(): ", func); + fprintf(stderr, "%s():%i: ", func, line); fprintf(stderr, "MALLOC() = %p", retval); fprintf(stderr, "\n"); return(retval); } -static void *CACKEY_DEBUG_FUNC_REALLOC(void *ptr, size_t size, const char *func) { +static void *CACKEY_DEBUG_FUNC_REALLOC(void *ptr, size_t size, const char *func, int line) { void *retval; retval = realloc(ptr, size); if (retval != ptr) { - fprintf(stderr, "%s(): ", func); + fprintf(stderr, "%s():%i: ", func, line); fprintf(stderr, "REALLOC(%p) = %p", ptr, retval); fprintf(stderr, "\n"); } + return(retval); +} + +static char *CACKEY_DEBUG_FUNC_STRDUP(const char *ptr, const char *func, int line) { + char *retval; + + retval = strdup(ptr); + + fprintf(stderr, "%s():%i: ", func, line); + fprintf(stderr, "STRDUP_MALLOC() = %p", retval); + fprintf(stderr, "\n"); + return(retval); } static const char *CACKEY_DEBUG_FUNC_TAG_TO_STR(unsigned char tag) { switch (tag) { @@ -424,12 +436,16 @@ } return("INVALID"); } -# define malloc(x) CACKEY_DEBUG_FUNC_MALLOC(x, __func__) -# define realloc(x, y) CACKEY_DEBUG_FUNC_REALLOC(x, y, __func__) +# define malloc(x) CACKEY_DEBUG_FUNC_MALLOC(x, __func__, __LINE__) +# define realloc(x, y) CACKEY_DEBUG_FUNC_REALLOC(x, y, __func__, __LINE__) +# ifdef strdup +# undef strdup +# endif +# define strdup(x) CACKEY_DEBUG_FUNC_STRDUP(x, __func__, __LINE__) #else # define CACKEY_DEBUG_PRINTF(x...) /**/ # define CACKEY_DEBUG_PRINTBUF(f, x, y) /**/ # define CACKEY_DEBUG_PERROR(x) /**/ # define CACKEY_DEBUG_FUNC_TAG_TO_STR(x) "DEBUG_DISABLED" ADDED leakcheck/check-malloc-free.sh Index: leakcheck/check-malloc-free.sh ================================================================== --- leakcheck/check-malloc-free.sh +++ leakcheck/check-malloc-free.sh @@ -0,0 +1,53 @@ +#! /bin/bash + +TMPFILE="${TMPDIR:-/tmp}/malloc-free-check-$$${RANDOM}${RANDOM}${RANDOM}.tmp" + +egrep '(MALLOC|FREE|REALLOC)' "$@" | sed 's@^.*FREE(\(0x[0-9a-f]*\)).*$@free \1@;s@^.*MALLOC() = @malloc @;s@^.*REALLOC(\(0x[0-9a-f]*\)) = @realloc \1 @' > "${TMPFILE}" + +cat "${TMPFILE}" | while read op addr newaddr; do + case "${op}" in + malloc) + if [ -z "${alloclist}" ]; then + alloclist="${addr}" + else + alloclist="${alloclist} ${addr}" + fi + ;; + free) + if ! echo " ${alloclist} " | grep " ${addr} " >/dev/null; then + if [ -z "${alloclist}" ]; then + alloclist="!${addr}" + else + alloclist="${alloclist} !${addr}" + fi + + continue + fi + alloclist="$(echo " ${alloclist} " | sed "s@ ${addr} @ @;s@^ *@@;s@ *\$@@")" + ;; + realloc) + alloclist="$(echo " ${alloclist} " | sed "s@ ${addr} @ ${newaddr} @;s@^ *@@;s@ *\$@@")" + ;; + esac + + echo "${alloclist}" +done | tail -1 | while read leftovers; do + for leftover in ${leftovers}; do + case "${leftover}" in + !*) + leftover="$(echo "${leftover}" | cut -c 2-)" + + echo "Double freed or never allocated ${leftover}:" + grep "${leftover}" "$@" | sed 's@^@ @' + echo '' + ;; + *) + echo "Unfreed memory ${leftover}:" + grep "${leftover}" "$@" | sed 's@^@ @' + echo '' + ;; + esac + done +done + +rm -f "${TMPFILE}"