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).)


git-svn-id: svn://svn.code.sf.net/p/ctags/code/trunk@536 c5d04d22-be80-434c-894e-aa346cc9e8e8
This commit is contained in:
elliotth 2007-06-02 06:09:00 +00:00
parent 5d188ab6e2
commit 7d841621f4
15 changed files with 92 additions and 62 deletions

2
args.c
View File

@ -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;
}

7
asm.c
View File

@ -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;
}

1
beta.c
View File

@ -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 File

@ -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 @@ getNextChar:
}
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 File

@ -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 @@ getNextChar:
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 File

@ -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 File

@ -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)

1
main.c
View File

@ -302,6 +302,7 @@ static boolean createTagsForEntry (const char *const entryName)
else
resize = parseFile (entryName);
eStatFree (status);
return resize;
}

View File

@ -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 File

@ -250,6 +250,7 @@ static void findPascalTags (void)
}
} /* while not eof */
}
vStringDelete (name);
}
extern parserDefinition* PascalParser (void)

1
read.c
View File

@ -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);
}

View File

@ -203,6 +203,11 @@ extern const char *getExecutableName (void)
return ExecutableName;
}
extern const char *getExecutablePath (void)
{
return ExecutableProgram;
}
extern void error (
const errorSelection selection, const char *const format, ...)
{
@ -416,8 +421,7 @@ extern fileStatus *eStat (const char *const fileName)
static fileStatus file;
if (file.name == NULL || strcmp (fileName, file.name) != 0)
{
if (file.name != NULL)
eFree (file.name);
eStatFree (&file);
file.name = eStrdup (fileName);
if (lstat (file.name, &status) != 0)
file.exists = FALSE;
@ -445,6 +449,15 @@ extern fileStatus *eStat (const char *const fileName)
return &file;
}
extern void eStatFree (fileStatus *status)
{
if (status->name != NULL)
{
eFree (status->name);
status->name = NULL;
}
}
extern boolean doesFileExist (const char *const fileName)
{
fileStatus *status = eStat (fileName);
@ -851,6 +864,7 @@ extern FILE *tempFile (const char *const mode, char **const pName)
name = xMalloc (strlen (tmpdir) + 1 + strlen (pattern) + 1, char);
sprintf (name, "%s%c%s", tmpdir, OUTPUT_PATH_SEPARATOR, pattern);
fd = mkstemp (name);
eStatFree (file);
#elif defined(HAVE_TEMPNAM)
name = tempnam (TMPDIR, "tags");
if (name == NULL)

View File

@ -84,6 +84,7 @@ typedef struct {
extern void freeRoutineResources (void);
extern void setExecutableName (const char *const path);
extern const char *getExecutableName (void);
extern const char *getExecutablePath (void);
extern void error (const errorSelection selection, const char *const format, ...) __printf__ (2, 3);
/* Memory allocation functions */
@ -111,6 +112,7 @@ extern char* newUpperString (const char* str);
/* File system functions */
extern void setCurrentDirectory (void);
extern fileStatus *eStat (const char *const fileName);
extern void eStatFree (fileStatus *status);
extern boolean doesFileExist (const char *const fileName);
extern boolean isRecursiveLink (const char* const dirName);
extern boolean isSameFile (const char *const name1, const char *const name2);

1
sml.c
View File

@ -146,6 +146,7 @@ static smlKind findNextIdentifier (const unsigned char **cp)
if (strcmp (id, SmlKeywordTypes [i].keyword) == 0)
result = SmlKeywordTypes [i].kind;
}
vStringDelete (identifier);
return result;
}

9
sql.c
View File

@ -455,11 +455,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_sql);
result = (keywordId) lookupKeyword (vStringValue (keyword), Lang_sql);
vStringDelete (keyword);
return result;
}
static void readToken (tokenInfo *const token)