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:
15
ChangeLog
15
ChangeLog
@@ -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.
|
||||
|
||||
54
src/input.cc
54
src/input.cc
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -121,6 +121,11 @@ Keyword_Factory::~Keyword_Factory ()
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
char empty_string[1] = "";
|
||||
|
||||
|
||||
#ifndef __OPTIMIZE__
|
||||
|
||||
#define INLINE /* not inline */
|
||||
|
||||
@@ -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
|
||||
|
||||
109
src/main.cc
109
src/main.cc
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 :
|
||||
|
||||
|
||||
Reference in New Issue
Block a user