From 5c6115c6011237f1044eb922b30bbf4cead60a58 Mon Sep 17 00:00:00 2001 From: david parsons Date: Thu, 3 Apr 2008 11:22:07 -0700 Subject: [PATCH] 1. Add the new `amalloc` module, which (if enabled with --enable-amalloc) replaced malloc and its ilk with versions that attempt to maintain a linked list of allocated blocks that can be printed to stderr with the `adump()` function. 2. Clean up a couple more places where I leak memory during the first level parse. 3. tweak cstring.h to try to chase down places where the C compiler might optimize EXPAND() into producing broken code. --- Makefile.in | 2 +- amalloc.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++ amalloc.h | 29 ++++++++++++++++ configure.sh | 11 +++++- cstring.h | 9 ++--- docheader.c | 1 + dumptree.c | 1 + generate.c | 2 +- main.c | 2 ++ markdown.c | 24 +++++++++---- markdown.h | 1 + mkd2html.c | 1 + mkdio.c | 1 + mkdio.h | 1 + theme.c | 1 + 15 files changed, 171 insertions(+), 13 deletions(-) create mode 100644 amalloc.c create mode 100644 amalloc.h diff --git a/Makefile.in b/Makefile.in index 6409557..d3362ce 100644 --- a/Makefile.in +++ b/Makefile.in @@ -11,7 +11,7 @@ PGMS=markdown SAMPLE_PGMS=mkd2html @THEME@SAMPLE_PGMS+= theme MKDLIB=libmarkdown.a -OBJS=mkdio.o markdown.o dumptree.o generate.o docheader.o version.o +OBJS=mkdio.o markdown.o dumptree.o generate.o docheader.o version.o @AMALLOC@ all: $(PGMS) $(SAMPLE_PGMS) diff --git a/amalloc.c b/amalloc.c new file mode 100644 index 0000000..acaa62d --- /dev/null +++ b/amalloc.c @@ -0,0 +1,98 @@ +/* + * debugging malloc()/realloc()/calloc()/free() that attempts + * to keep track of just what's been allocated today. + */ + +#include +#include + +#define MAGIC 0x1f2e3d4c + +struct alist { int magic, size; struct alist *next, *last; }; + +static struct alist list = { 0, 0, 0, 0 }; + +void * +acalloc(int size, int count) +{ + struct alist *ret = calloc(size + sizeof(struct alist), count); + + if ( ret ) { + ret->magic = MAGIC; + ret->size = size * count; + if ( list.next ) { + ret->next = list.next; + ret->last = &list; + ret->next->last = ret; + list.next = ret; + } + else { + ret->last = ret->next = &list; + list.next = list.last = ret; + } + return ret+1; + } + return 0; +} + + +void* +amalloc(int size) +{ + return acalloc(size,1); +} + + +void * +afree(void *ptr) +{ + struct alist *p2 = ((struct alist*)ptr)-1; + + if ( p2->magic == MAGIC ) { + p2->last->next = p2->next; + p2->next->last = p2->last; + free(p2); + } + else + free(ptr); +} + + +void * +arealloc(void *ptr, int size) +{ + struct alist *p2 = ((struct alist*)ptr)-1; + struct alist save; + + if ( p2->magic == MAGIC ) { + save.next = p2->next; + save.last = p2->last; + p2 = realloc(p2, sizeof(p2) + size); + + if ( p2 ) { + p2->size = size; + p2->next->last = p2; + p2->last->next = p2; + return p2+1; + } + else { + save.next->last = save.last; + save.last->next = save.next; + return 0; + } + } + return realloc(ptr, size); +} + + +void +adump() +{ + struct alist *p; + + + for ( p = list.next; p && (p != &list); p = p->next ) { + fprintf(stderr, "allocated: %d byte%s\n", p->size, (p->size==1) ? "" : "s"); + fprintf(stderr, " [%.*s]\n", p->size, p+1); + } +} diff --git a/amalloc.h b/amalloc.h new file mode 100644 index 0000000..43ca985 --- /dev/null +++ b/amalloc.h @@ -0,0 +1,29 @@ +/* + * debugging malloc()/realloc()/calloc()/free() that attempts + * to keep track of just what's been allocated today. + */ +#ifndef AMALLOC_D +#define AMALLOC_D + +#include "config.h" + +#ifdef USE_AMALLOC + +extern void *amalloc(int); +extern void *acalloc(int,int); +extern void *arealloc(void*,int); +extern void afree(void*); +extern void adump(); + +#define malloc amalloc +#define calloc acalloc +#define realloc arealloc +#define free afree + +#else + +#define adump() (void)1 + +#endif + +#endif/*AMALLOC_D*/ diff --git a/configure.sh b/configure.sh index 174d5ef..3f1485f 100755 --- a/configure.sh +++ b/configure.sh @@ -9,7 +9,8 @@ # ac_help='--enable-dl-tag Use the DL tag extension --enable-pandoc-header Use pandoc-style header blocks ---with-tabstops=N Set tabstops to N characters (default is 4)' +--with-tabstops=N Set tabstops to N characters (default is 4) +--enable-amalloc Enable memory allocation debugging' LOCAL_AC_OPTIONS=' set=`locals $*`; @@ -99,6 +100,14 @@ fi AC_DEFINE 'TABSTOP' $TABSTOP AC_SUB 'TABSTOP' $TABSTOP + +if [ "$WITH_AMALLOC" ]; then + AC_DEFINE 'USE_AMALLOC' 1 + AC_SUB 'AMALLOC' 'amalloc.o' +else + AC_SUB 'AMALLOC' '' +fi + [ "$OS_FREEBSD" -o "$OS_DRAGONFLY" ] || AC_CHECK_HEADERS malloc.h [ "$WITH_DL_TAG" ] && AC_DEFINE 'DL_TAG_EXTENSION' '1' diff --git a/cstring.h b/cstring.h index 79e396f..1b561a3 100644 --- a/cstring.h +++ b/cstring.h @@ -10,16 +10,17 @@ #include #include +#include "amalloc.h" + /* expandable Pascal-style string. */ #define STRING(type) struct { type *text; int size, alloc; } #define RESERVE(x,c) (x).text = malloc(sizeof T(x)[0] * (((x).size=0),((x).alloc=(c))) ) #define CREATE(x) RESERVE(x,100) -#define EXPAND(x) (x).text[((x).size < (x).alloc \ - ? 0 \ - : !((x).text = realloc((x).text, sizeof T(x)[0] * ((x).alloc += 100)))), \ - (x).size++] +#define EXPAND(x) ((x).size++)[((x).size < (x).alloc) \ + ? (x).text \ + : (x).text = realloc((x).text, sizeof T(x)[0] * ((x).alloc += 100))] #define DELETE(x) (x).alloc ? (free(T(x)), S(x) = (x).alloc = 0) \ : ( S(x) = 0 ) diff --git a/docheader.c b/docheader.c index aa8ff21..0b56114 100644 --- a/docheader.c +++ b/docheader.c @@ -12,6 +12,7 @@ #include "cstring.h" #include "markdown.h" +#include "amalloc.h" #define afterdle(t) (T((t)->text) + (t)->dle) diff --git a/dumptree.c b/dumptree.c index a5fc865..cc0a0c7 100755 --- a/dumptree.c +++ b/dumptree.c @@ -7,6 +7,7 @@ #include #include "markdown.h" #include "cstring.h" +#include "amalloc.h" struct frame { int indent; diff --git a/generate.c b/generate.c index 5e36db1..b8bd440 100644 --- a/generate.c +++ b/generate.c @@ -15,6 +15,7 @@ #include "cstring.h" #include "markdown.h" +#include "amalloc.h" /* prefixes for */ @@ -1196,4 +1197,3 @@ mkd_style(Document *d, FILE *f) return stylesheets(d->code, f); return EOF; } - diff --git a/main.c b/main.c index 0a27581..0cb1ce7 100644 --- a/main.c +++ b/main.c @@ -15,6 +15,7 @@ #include #include "config.h" +#include "amalloc.h" #if HAVE_LIBGEN_H #include @@ -137,5 +138,6 @@ main(int argc, char **argv) rc = mkd_dump(doc, stdout, 0, argc ? basename(argv[0]) : "stdin"); else rc = markdown(doc, stdout, flags); + adump(); exit( (rc == 0) ? 0 : errno ); } diff --git a/markdown.c b/markdown.c index f9e9496..b49f008 100644 --- a/markdown.c +++ b/markdown.c @@ -15,6 +15,7 @@ #include "cstring.h" #include "markdown.h" +#include "amalloc.h" /* block-level tags for passing html blocks through the blender */ @@ -669,7 +670,12 @@ listblock(Paragraph *top, int trim, MMIOT *f) if ( !(q = skipempty(text)) || (islist(q,&trim) != top->typ) ) break; - para = (q != text); + if ( para = (q != text) ) { + Line anchor; + + anchor.next = text; + freeLineRange(&anchor, q); + } if ( para && (top->typ != DL) ) p->down->align = PARA; } @@ -699,7 +705,7 @@ addfootnote(Line *p, MMIOT* f) { int j, i; int c; - Line *p2 = p->next; + Line *np = p->next; Footnote *foot = &EXPAND(f->footnotes); @@ -729,9 +735,11 @@ addfootnote(Line *p, MMIOT* f) } - if ( (j >= S(p->text)) && p2 && p2->dle && tgood(T(p2->text)[p2->dle]) ) { - j = p2->dle; - p = p2; + if ( (j >= S(p->text)) && np && np->dle && tgood(T(np->text)[np->dle]) ) { + freeLine(p); + p = np; + np = p->next; + j = p->dle; } if ( (c = tgood(T(p->text)[j])) ) { @@ -751,7 +759,8 @@ addfootnote(Line *p, MMIOT* f) EXPAND(foot->title) = 0; } - return p->next; + freeLine(p); + return np; } @@ -798,6 +807,7 @@ compile(Line *ptr, int toplevel, MMIOT *f) ParagraphRoot d = { 0, 0 }; Paragraph *p = 0; char *key; + Line *r; int para = toplevel; int hdr_type, list_type, indent; @@ -817,7 +827,9 @@ compile(Line *ptr, int toplevel, MMIOT *f) } else if ( ishr(ptr) ) { p = Pp(&d, 0, HR); + r = ptr; ptr = ptr->next; + freeLine(r); } else if (( list_type = islist(ptr, &indent) )) { p = Pp(&d, ptr, list_type); diff --git a/markdown.h b/markdown.h index 9b062e0..42dafbe 100644 --- a/markdown.h +++ b/markdown.h @@ -2,6 +2,7 @@ #define _MARKDOWN_D #include "cstring.h" +#include "amalloc.h" /* reference-style links (and images) are stored in an array * of footnotes. diff --git a/mkd2html.c b/mkd2html.c index df88aa2..eaf5362 100644 --- a/mkd2html.c +++ b/mkd2html.c @@ -35,6 +35,7 @@ #include "mkdio.h" #include "cstring.h" +#include "amalloc.h" char *pgm = "mkd2html"; diff --git a/mkdio.c b/mkdio.c index d55bde7..e1b2b77 100644 --- a/mkdio.c +++ b/mkdio.c @@ -12,6 +12,7 @@ #include "cstring.h" #include "markdown.h" +#include "amalloc.h" typedef ANCHOR(Line) LineAnchor; diff --git a/mkdio.h b/mkdio.h index 936ca86..c0a7968 100644 --- a/mkdio.h +++ b/mkdio.h @@ -2,6 +2,7 @@ #define _MKDIO_D #include +#include "amalloc.h" typedef void MMIOT; diff --git a/theme.c b/theme.c index b6007bb..3b8dafa 100644 --- a/theme.c +++ b/theme.c @@ -31,6 +31,7 @@ #include "mkdio.h" #include "cstring.h" +#include "amalloc.h" char *pgm = "theme"; char *output = 0;