1
0
mirror of https://git.savannah.gnu.org/git/gperf.git synced 2025-12-02 13:09:22 +00:00

Fix memory leaks.

This commit is contained in:
Bruno Haible
2003-01-23 12:03:33 +00:00
parent 83440a2aed
commit a9916548fa
8 changed files with 141 additions and 60 deletions

View File

@@ -1,5 +1,20 @@
2002-11-10 Bruno Haible <bruno@clisp.org>
Fix memory leaks.
* src/keyword.h (empty_string): New declaration.
* src/keyword.cc (empty_string): New variable.
* src/input.h (Input::_input): Make public.
(Input::_input_end): New field.
* src/input.cc (read_input): When removing leading whitespace from
struct_decl, reallocate it. For rest, use empty_string instead of "".
Set _input_end.
(Input::~Input): Delete _struct_decl, _struct_tag, _return_type.
* src/search.cc (Search::prepare): When removing an element from
the keyword list, delete the list node.
(Search::~Search): Delete _occurrences, _asso_values.
* src/main.cc (main): Between Search::~Search and Input::~Input,
destroy the keyword list.
Rewrite the input routines.
* src/input.h: Don't include read-line.h.
(Input): Don't inherit from class Read_Line.

View File

@@ -299,9 +299,19 @@ Input::read_input ()
if (struct_decl)
{
/* Drop leading whitespace. */
while (struct_decl[0] == '\n' || struct_decl[0] == ' '
|| struct_decl[0] == '\t')
struct_decl++;
{
char *p = struct_decl;
while (p[0] == '\n' || p[0] == ' ' || p[0] == '\t')
p++;
if (p != struct_decl)
{
size_t len = strlen (p);
char *new_struct_decl = new char[len + 1];
memcpy (new_struct_decl, p, len + 1);
delete[] struct_decl;
struct_decl = new_struct_decl;
}
}
/* Drop trailing whitespace. */
for (char *p = struct_decl + strlen (struct_decl); p > struct_decl;)
if (p[-1] == '\n' || p[-1] == ' ' || p[-1] == '\t')
@@ -315,20 +325,19 @@ Input::read_input ()
" for option --struct-type\n");
exit (1);
}
if (struct_decl)
{
/* Ensure trailing semicolon. */
size_t old_len = strlen (struct_decl);
if (struct_decl[old_len - 1] != ';')
{
char *new_struct_decl = new char[old_len + 2];
memcpy (new_struct_decl, struct_decl, old_len);
new_struct_decl[old_len] = ';';
new_struct_decl[old_len + 1] = '\0';
delete[] struct_decl;
struct_decl = new_struct_decl;
}
}
{
/* Ensure trailing semicolon. */
size_t old_len = strlen (struct_decl);
if (struct_decl[old_len - 1] != ';')
{
char *new_struct_decl = new char[old_len + 2];
memcpy (new_struct_decl, struct_decl, old_len);
new_struct_decl[old_len] = ';';
new_struct_decl[old_len + 1] = '\0';
delete[] struct_decl;
struct_decl = new_struct_decl;
}
}
/* Set _struct_decl to the entire declaration. */
_struct_decl = struct_decl;
/* Set _struct_tag to the naked "struct something". */
@@ -529,7 +538,7 @@ Input::read_input ()
rest = line_rest;
}
else
rest = "";
rest = empty_string;
}
else
{
@@ -541,7 +550,7 @@ Input::read_input ()
{
keyword = line;
keyword_length = lp - line;
rest = "";
rest = empty_string;
break;
}
if (strchr (delimiters, *lp) != NULL)
@@ -560,7 +569,7 @@ Input::read_input ()
rest = line_rest;
}
else
rest = "";
rest = empty_string;
break;
}
lp++;
@@ -588,9 +597,14 @@ Input::read_input ()
/* To be freed in the destructor. */
_input = input;
_input_end = input_end;
}
Input::~Input ()
{
/* Free allocated memory. */
delete[] _return_type;
delete[] _struct_tag;
delete[] _struct_decl;
delete[] _input;
}

View File

@@ -40,9 +40,10 @@ private:
FILE * _stream;
/* Creates the keywords. */
Keyword_Factory * const _factory;
public:
/* Memory block containing the entire input. */
char * _input;
public:
char * _input_end;
/* The C code from the declarations section. */
const char * _verbatim_declarations;
const char * _verbatim_declarations_end;

View File

@@ -121,6 +121,11 @@ Keyword_Factory::~Keyword_Factory ()
}
/* ------------------------------------------------------------------------- */
char empty_string[1] = "";
#ifndef __OPTIMIZE__
#define INLINE /* not inline */

View File

@@ -86,11 +86,14 @@ public:
virtual ~Keyword_Factory ();
/* Creates a new Keyword. */
virtual /*abstract */ Keyword *
virtual /*abstract*/ Keyword *
create_keyword (const char *allchars, int allchars_length,
const char *rest) = 0;
};
/* A statically allocated empty string. */
extern char empty_string[1];
#ifdef __OPTIMIZE__
#define INLINE inline

View File

@@ -49,6 +49,8 @@ KeywordExt_Factory::create_keyword (const char *allchars, int allchars_length, c
int
main (int argc, char *argv[])
{
int exitcode;
/* Set the Options. Open the input file and assign stdin to it. */
option.parse_options (argc, argv);
@@ -61,46 +63,79 @@ main (int argc, char *argv[])
exit (1);
}
/* Initialize the keyword list. */
KeywordExt_Factory factory;
Input inputter (stdin, &factory);
inputter.read_input ();
/* We can cast the keyword list to KeywordExt_List* because its list
elements were created by KeywordExt_Factory. */
KeywordExt_List* list = static_cast<KeywordExt_List*>(inputter._head);
{
/* Initialize the keyword list. */
KeywordExt_Factory factory;
Input inputter (stdin, &factory);
inputter.read_input ();
/* We can cast the keyword list to KeywordExt_List* because its list
elements were created by KeywordExt_Factory. */
KeywordExt_List* list = static_cast<KeywordExt_List*>(inputter._head);
/* Search for a good hash function. */
Search searcher (list);
searcher.optimize ();
/* Output the hash function code. */
Output outputter (searcher._head,
inputter._struct_decl,
inputter._return_type,
inputter._struct_tag,
inputter._verbatim_declarations,
inputter._verbatim_declarations_end,
inputter._verbatim_declarations_lineno,
inputter._verbatim_code,
inputter._verbatim_code_end,
inputter._verbatim_code_lineno,
searcher._total_keys,
searcher._total_duplicates,
searcher._max_key_len,
searcher._min_key_len,
searcher._alpha_size,
searcher._occurrences,
searcher._asso_values);
outputter.output ();
/* Check for write error on stdout. */
int status = 0;
if (fflush (stdout) || ferror (stdout))
{
fprintf (stderr, "error while writing output file\n");
status = 1;
/* Search for a good hash function. */
Search searcher (list);
searcher.optimize ();
list = searcher._head;
{
/* Output the hash function code. */
Output outputter (searcher._head,
inputter._struct_decl,
inputter._return_type,
inputter._struct_tag,
inputter._verbatim_declarations,
inputter._verbatim_declarations_end,
inputter._verbatim_declarations_lineno,
inputter._verbatim_code,
inputter._verbatim_code_end,
inputter._verbatim_code_lineno,
searcher._total_keys,
searcher._total_duplicates,
searcher._max_key_len,
searcher._min_key_len,
searcher._alpha_size,
searcher._occurrences,
searcher._asso_values);
outputter.output ();
/* Check for write error on stdout. */
exitcode = 0;
if (fflush (stdout) || ferror (stdout))
{
fprintf (stderr, "error while writing output file\n");
exitcode = 1;
}
/* Here we run the Output destructor. */
}
/* Here we run the Search destructor. */
}
/* Also delete the list that was allocated inside Input and reordered
inside Search. */
for (KeywordExt_List *ptr = list; ptr; ptr = ptr->rest())
{
KeywordExt *keyword = ptr->first();
do
{
KeywordExt *next_keyword = keyword->_duplicate_link;
delete[] keyword->_selchars;
if (keyword->_rest != empty_string)
delete[] keyword->_rest;
if (!(keyword->_allchars >= inputter._input
&& keyword->_allchars < inputter._input_end))
delete[] keyword->_allchars;
delete keyword;
keyword = next_keyword;
}
while (keyword != NULL);
}
delete_list (list);
/* Here we run the Input destructor. */
}
/* Don't use exit() here, it skips the destructors. */
return status;
return exitcode;
}

View File

@@ -94,10 +94,11 @@ Search::prepare ()
Hash_Table representatives (_list_len, option[NOLENGTH]);
KeywordExt_List *prev = NULL; /* list node before temp */
for (temp = _head; temp; temp = temp->rest())
for (temp = _head; temp; )
{
KeywordExt *keyword = temp->first();
KeywordExt *other_keyword = representatives.insert (keyword);
KeywordExt_List *garbage = NULL;
if (other_keyword)
{
@@ -105,6 +106,7 @@ Search::prepare ()
_list_len--;
/* Remove keyword from the main list. */
prev->rest() = temp->rest();
garbage = temp;
/* And insert it on other_keyword's duplicate list. */
keyword->_duplicate_link = other_keyword->_duplicate_link;
other_keyword->_duplicate_link = keyword;
@@ -121,6 +123,9 @@ Search::prepare ()
keyword->_duplicate_link = NULL;
prev = temp;
}
temp = temp->rest();
if (garbage)
delete garbage;
}
}
@@ -798,4 +803,6 @@ Search::~Search ()
fprintf (stderr, "End dumping list.\n\n");
}
delete[] _asso_values;
delete[] _occurrences;
}

View File

@@ -48,6 +48,7 @@ SHELL = /bin/sh
VPATH = $(srcdir)
GPERF = ../src/gperf
#GPERF = valgrind --num-callers=20 --leak-check=yes --leak-resolution=high --show-reachable=yes ../src/gperf
all :