Permalink
Browse files

trunk/args.c:

trunk/asm.c: 
trunk/beta.c: 
trunk/eiffel.c: 
trunk/fortran.c: 
trunk/jscript.c: 
trunk/lregex.c: 
trunk/main.c: 
trunk/options.c: 
trunk/pascal.c: 
trunk/read.c: 
trunk/routines.c: 
trunk/routines.h: 
trunk/sml.c: 
trunk/sql.c: fix almost all our current memory leaks. Based on a patch from Dmitry Antipov, but also using his vString leak detector and valgrind(1) to find new ones and ones he missed. Three known leaks remain. The first is in parseLongOption. There's also one in "fortran.c" and another in "sql.c":

helium:~/Projects/ctags/trunk$ valgrind --leak-check=full --show-reachable=yes ./dctags -f - Test/*
==3056== Memcheck, a memory error detector.
==3056== Copyright (C) 2002-2006, and GNU GPL'd, by Julian Seward et al.
==3056== Using LibVEX rev 1658, a library for dynamic binary translation.
==3056== Copyright (C) 2004-2006, and GNU GPL'd, by OpenWorks LLP.
==3056== Using valgrind-3.2.1-Debian, a dynamic binary instrumentation framework.
==3056== Copyright (C) 2000-2006, and GNU GPL'd, by Julian Seward et al.
==3056== For more details, rerun with: -v
==3056== 
.
.
.
==3056== 
==3056== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 13 from 1)
==3056== malloc/free: in use at exit: 708 bytes in 22 blocks.
==3056== malloc/free: 36,126 allocs, 36,104 frees, 1,584,216 bytes allocated.
==3056== For counts of detected errors, rerun with: -v
==3056== searching for pointers to 22 not-freed blocks.
==3056== checked 68,184 bytes.
==3056== 
==3056== 68 bytes in 2 blocks are definitely lost in loss record 1 of 2
==3056==    at 0x4021620: malloc (vg_replace_malloc.c:149)
==3056==    by 0x806347E: eMalloc (routines.c:238)
==3056==    by 0x8065B68: newToken (sql.c:347)
==3056==    by 0x80662BB: parseSubProgram (sql.c:688)
==3056==    by 0x8067867: parseSqlFile (sql.c:1782)
==3056==    by 0x8067934: findSqlTags (sql.c:1810)
==3056==    by 0x8060760: createTagsForFile (parse.c:618)
==3056==    by 0x8060810: createTagsWithFallback (parse.c:640)
==3056==    by 0x80608DC: parseFile (parse.c:667)
==3056==    by 0x805B7D6: createTagsForEntry (main.c:303)
==3056==    by 0x805B811: createTagsForArgs (main.c:348)
==3056==    by 0x805BD6F: makeTags (main.c:494)
==3056== 
==3056== 
==3056== 640 bytes in 20 blocks are still reachable in loss record 2 of 2
==3056==    at 0x4021620: malloc (vg_replace_malloc.c:149)
==3056==    by 0x806347E: eMalloc (routines.c:238)
==3056==    by 0x806AEE2: vStringNew (vstring.c:116)
==3056==    by 0x80542C0: newToken (fortran.c:419)
==3056==    by 0x8054309: newTokenFrom (fortran.c:429)
==3056==    by 0x80562E5: parseInterfaceBlock (fortran.c:1709)
==3056==    by 0x805661D: parseDeclarationConstruct (fortran.c:1834)
==3056==    by 0x805679F: parseSpecificationPart (fortran.c:1901)
==3056==    by 0x80569F5: parseModule (fortran.c:1990)
==3056==    by 0x8056E05: parseProgramUnit (fortran.c:2142)
==3056==    by 0x8056F37: findFortranTags (fortran.c:2183)
==3056==    by 0x806077A: createTagsForFile (parse.c:620)
==3056== 
==3056== LEAK SUMMARY:
==3056==    definitely lost: 68 bytes in 2 blocks.
==3056==      possibly lost: 0 bytes in 0 blocks.
==3056==    still reachable: 640 bytes in 20 blocks.
==3056==         suppressed: 0 bytes in 0 blocks.

I think they're both awkward longjmp(3)/setjmp(3)-related leaks, and I don't currently have a good solution. ("eiffel.c" cunningly only calls newToken once, before calling setjmp(3).)
  • Loading branch information...
1 parent bc2f4db commit 58cf1cf50140b36df45b7d0c24a3a7c752be3944 Elliott Hughes committed Jun 2, 2007
Showing with 92 additions and 62 deletions.
  1. +1 −1 args.c
  2. +3 −4 asm.c
  3. +1 −0 beta.c
  4. +23 −20 eiffel.c
  5. +19 −22 fortran.c
  6. +9 −6 jscript.c
  7. +5 −1 lregex.c
  8. +1 −0 main.c
  9. +4 −2 options.c
  10. +1 −0 pascal.c
  11. +1 −0 read.c
  12. +16 −2 routines.c
  13. +2 −0 routines.h
  14. +1 −0 sml.c
  15. +5 −4 sql.c
View
2 args.c
@@ -150,8 +150,8 @@ static char* nextFileLine (FILE* const fp)
vStringStripTrailing (vs);
result = xMalloc (vStringLength (vs) + 1, char);
strcpy (result, vStringValue (vs));
- vStringDelete (vs);
}
+ vStringDelete (vs);
}
return result;
}
View
7 asm.c
@@ -129,13 +129,12 @@ static void buildAsmKeywordHash (void)
static opKeyword analyzeOperator (const vString *const op)
{
- static vString *keyword = NULL;
- opKeyword result = OP_UNDEFINED;
+ vString *keyword = vStringNew ();
+ opKeyword result;
- if (keyword == NULL)
- keyword = vStringNew ();
vStringCopyToLower (keyword, op);
result = (opKeyword) lookupKeyword (vStringValue (keyword), Lang_asm);
+ vStringDelete (keyword);
return result;
}
View
1 beta.c
@@ -304,6 +304,7 @@ static void findBetaTags (void)
endofline:
inquote = FALSE; /* This shouldn't really make a difference */
} while (!feof (File.fp));
+ vStringDelete (line);
}
extern parserDefinition* BetaParser (void)
View
@@ -381,11 +381,7 @@ static int skipToCharacter (const int c)
*/
static vString *parseInteger (int c)
{
- static vString *string = NULL;
-
- if (string == NULL)
- string = vStringNew ();
- vStringClear (string);
+ vString *string = vStringNew ();
if (c == '\0')
c = fileGetc ();
@@ -409,23 +405,26 @@ static vString *parseInteger (int c)
static vString *parseNumeric (int c)
{
- static vString *string = NULL;
-
- if (string == NULL)
- string = vStringNew ();
- vStringCopy (string, parseInteger (c));
+ vString *string = vStringNew ();
+ vString *integer = parseInteger (c);
+ vStringCopy (string, integer);
+ vStringDelete (integer);
c = fileGetc ();
if (c == '.')
{
+ integer = parseInteger ('\0');
vStringPut (string, c);
- vStringCat (string, parseInteger ('\0'));
+ vStringCat (string, integer);
+ vStringDelete (integer);
c = fileGetc ();
}
if (tolower (c) == 'e')
{
+ integer = parseInteger ('\0');
vStringPut (string, c);
- vStringCat (string, parseInteger ('\0'));
+ vStringCat (string, integer);
+ vStringDelete (integer);
}
else if (!isspace (c))
fileUngetc (c);
@@ -475,6 +474,7 @@ static int parseEscapedCharacter (void)
vString *string = parseInteger ('\0');
const char *value = vStringValue (string);
const unsigned long ascii = atol (value);
+ vStringDelete (string);
c = fileGetc ();
if (c == '/' && ascii < 256)
@@ -507,8 +507,8 @@ static void parseString (vString *const string)
boolean verbatim = FALSE;
boolean align = FALSE;
boolean end = FALSE;
- vString *verbatimCloser = NULL;
- vString *lastLine = NULL;
+ vString *verbatimCloser = vStringNew ();
+ vString *lastLine = vStringNew ();
int prev = '\0';
int c;
@@ -532,8 +532,8 @@ static void parseString (vString *const string)
if (prev == '[' /* || prev == '{' */)
{
verbatim = TRUE;
- verbatimCloser = vStringNew ();
- lastLine = vStringNew ();
+ vStringClear (verbatimCloser);
+ vStringClear (lastLine);
if (prev == '{')
vStringPut (verbatimCloser, '}');
else
@@ -565,6 +565,8 @@ static void parseString (vString *const string)
}
}
vStringTerminate (string);
+ vStringDelete (lastLine);
+ vStringDelete (verbatimCloser);
}
/* Read a C identifier beginning with "firstChar" and places it into "name".
@@ -601,13 +603,12 @@ static void parseFreeOperator (vString *const string, const int firstChar)
static keywordId analyzeToken (vString *const name)
{
- static vString *keyword = NULL;
+ vString *keyword = vStringNew ();
keywordId id;
- if (keyword == NULL)
- keyword = vStringNew ();
vStringCopyToLower (keyword, name);
id = (keywordId) lookupKeyword (vStringValue (keyword), Lang_eiffel);
+ vStringDelete (keyword);
return id;
}
@@ -728,7 +729,9 @@ static void readToken (tokenInfo *const token)
}
else if (isdigit (c))
{
- vStringCat (token->string, parseNumeric (c));
+ vString* numeric = parseNumeric (c);
+ vStringCat (token->string, numeric);
+ vStringDelete (numeric);
token->type = TOKEN_NUMERIC;
}
else if (isFreeOperatorChar (c))
View
@@ -519,13 +519,10 @@ static void makeLabelTag (vString *const label)
static lineType getLineType (void)
{
- static vString *label = NULL;
+ vString *label = vStringNew ();
int column = 0;
lineType type = LTYPE_UNDETERMINED;
- if (label == NULL)
- label = vStringNew ();
-
do /* read in first 6 "margin" characters */
{
int c = fileGetc ();
@@ -589,8 +586,8 @@ static lineType getLineType (void)
{
vStringTerminate (label);
makeLabelTag (label);
- vStringClear (label);
}
+ vStringDelete (label);
return type;
}
@@ -768,11 +765,7 @@ static void ungetChar (const int c)
*/
static vString *parseInteger (int c)
{
- static vString *string = NULL;
-
- if (string == NULL)
- string = vStringNew ();
- vStringClear (string);
+ vString *string = vStringNew ();
if (c == '-')
{
@@ -801,23 +794,26 @@ static vString *parseInteger (int c)
static vString *parseNumeric (int c)
{
- static vString *string = NULL;
-
- if (string == NULL)
- string = vStringNew ();
- vStringCopy (string, parseInteger (c));
+ vString *string = vStringNew ();
+ vString *integer = parseInteger (c);
+ vStringCopy (string, integer);
+ vStringDelete (integer);
c = getChar ();
if (c == '.')
{
+ integer = parseInteger ('\0');
vStringPut (string, c);
- vStringCat (string, parseInteger ('\0'));
+ vStringCat (string, integer);
+ vStringDelete (integer);
c = getChar ();
}
if (tolower (c) == 'e')
{
+ integer = parseInteger ('\0');
vStringPut (string, c);
- vStringCat (string, parseInteger ('\0'));
+ vStringCat (string, integer);
+ vStringDelete (integer);
}
else
ungetChar (c);
@@ -873,13 +869,12 @@ static void parseIdentifier (vString *const string, const int firstChar)
*/
static keywordId analyzeToken (vString *const name)
{
- static vString *keyword = NULL;
+ vString *keyword = vStringNew ();
keywordId id;
- if (keyword == NULL)
- keyword = vStringNew ();
vStringCopyToLower (keyword, name);
id = (keywordId) lookupKeyword (vStringValue (keyword), Lang_fortran);
+ vStringDelete (keyword);
return id;
}
@@ -1046,7 +1041,9 @@ static void readToken (tokenInfo *const token)
readIdentifier (token, c);
else if (isdigit (c))
{
- vStringCat (token->string, parseNumeric (c));
+ vString *numeric = parseNumeric (c);
+ vStringCat (token->string, numeric);
+ vStringDelete (numeric);
token->type = TOKEN_NUMERIC;
}
else
@@ -1968,7 +1965,7 @@ static void parseInternalSubprogramPart (tokenInfo *const token)
}
/* module is
- * mudule-stmt (is MODULE module-name)
+ * module-stmt (is MODULE module-name)
* [specification-part]
* [module-subprogram-part]
* end-module-stmt (is END [MODULE [module-name]])
View
@@ -316,11 +316,12 @@ static void parseIdentifier (vString *const string, const int firstChar)
static keywordId analyzeToken (vString *const name)
{
- static vString *keyword = NULL;
- if (keyword == NULL)
- keyword = vStringNew ();
+ vString *keyword = vStringNew ();
+ keywordId result;
vStringCopyToLower (keyword, name);
- return (keywordId) lookupKeyword (vStringValue (keyword), Lang_js);
+ result = (keywordId) lookupKeyword (vStringValue (keyword), Lang_js);
+ vStringDelete (keyword);
+ return result;
}
static void readToken (tokenInfo *const token)
@@ -1215,10 +1216,12 @@ static void initialize (const langType language)
static void findJsTags (void)
{
tokenInfo *const token = newToken ();
- exception_t exception = (exception_t) (setjmp (Exception));
+ exception_t exception;
+
ClassNames = stringListNew ();
FunctionNames = stringListNew ();
-
+
+ exception = (exception_t) (setjmp (Exception));
while (exception == ExceptionNone)
parseJsFile (token);
View
@@ -101,7 +101,7 @@ static int SetUpper = -1; /* upper language index in list */
static void clearPatternSet (const langType language)
{
- if (language < SetUpper)
+ if (language <= SetUpper)
{
patternSet* const set = Sets + language;
unsigned int i;
@@ -117,6 +117,10 @@ static void clearPatternSet (const langType language)
{
eFree (set->patterns [i].u.tag.name_pattern);
set->patterns [i].u.tag.name_pattern = NULL;
+ eFree (set->patterns [i].u.tag.kind.name);
+ set->patterns [i].u.tag.kind.name = NULL;
+ eFree (set->patterns [i].u.tag.kind.description);
+ set->patterns [i].u.tag.kind.description = NULL;
}
}
if (set->patterns != NULL)
View
1 main.c
@@ -302,6 +302,7 @@ static boolean createTagsForEntry (const char *const entryName)
else
resize = parseFile (entryName);
+ eStatFree (status);
return resize;
}
View
@@ -453,6 +453,8 @@ extern void testEtagsInvocation (void)
verbose ("Running in etags mode\n");
setEtagsMode ();
}
+ eFree (execName);
+ eFree (etags);
}
/*
@@ -487,13 +489,13 @@ static void parseLongOption (cookedArgs *const args, const char *item)
const char* const equal = strchr (item, '=');
if (equal == NULL)
{
- args->item = eStrdup (item);
+ args->item = eStrdup (item); /* FIXME: memory leak. */
args->parameter = "";
}
else
{
const size_t length = equal - item;
- args->item = xMalloc (length + 1, char);
+ args->item = xMalloc (length + 1, char); /* FIXME: memory leak. */
strncpy (args->item, item, length);
args->item [length] = '\0';
args->parameter = equal + 1;
View
@@ -250,6 +250,7 @@ static void findPascalTags (void)
}
} /* while not eof */
}
+ vStringDelete (name);
}
extern parserDefinition* PascalParser (void)
View
1 read.c
@@ -41,6 +41,7 @@ extern void freeSourceFileResources (void)
vStringDelete (File.name);
vStringDelete (File.path);
vStringDelete (File.source.name);
+ eFree (File.source.tagPath);
vStringDelete (File.line);
}
Oops, something went wrong.

0 comments on commit 58cf1cf

Please sign in to comment.