changeset 13970:c93b953f7d54

plug some memory leaks * oct-parse.yy, parse.h (cleanup_statement_list): New function. * toplev.cc (main_loop): Put cleanup_statement_list on the unwind_protect stack to delete the command list created by the parser instead of deleting it directly. * oct-parse.yy (parse_fcn_file, eval_string): Likewise. * input.cc (get_debug_input): Likewise. * pt-loop.cc (tree_simple_for_command::~tree_simple_for_command, tree_complex_for_command::~tree_complex_for_command): Also delete lhs expression. * pt-idx.cc (tree_index_expression::~tree_index_expression): Also delete contents of dyn_field list.
author John W. Eaton <jwe@octave.org>
date Thu, 01 Dec 2011 04:26:46 -0500
parents 3b5afcec526b
children 62c8205b3fab
files src/input.cc src/oct-parse.yy src/parse.h src/pt-idx.cc src/pt-loop.cc src/toplev.cc
diffstat 6 files changed, 48 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/src/input.cc	Thu Dec 01 04:04:50 2011 -0500
+++ b/src/input.cc	Thu Dec 01 04:26:46 2011 -0500
@@ -749,17 +749,15 @@
 
       if (retval == 0 && global_command)
         {
-          global_command->accept (*current_evaluator);
+          unwind_protect inner_frame;
 
-          // FIXME -- To avoid a memory leak, global_command should be
-          // deleted, I think.  But doing that here causes trouble if
-          // an error occurs while executing a debugging command
-          // (dbstep, for example). It's not clear to me why that
-          // happens.
-          //
-          // delete global_command;
-          //
-          // global_command = 0;
+          // Use an unwind-protect cleanup function so that the
+          // global_command list will be deleted in the event of an
+          // interrupt.
+
+          inner_frame.add_fcn (cleanup_statement_list, &global_command);
+
+          global_command->accept (*current_evaluator);
 
           if (octave_completion_matches_called)
             octave_completion_matches_called = false;
--- a/src/oct-parse.yy	Thu Dec 01 04:04:50 2011 -0500
+++ b/src/oct-parse.yy	Thu Dec 01 04:26:46 2011 -0500
@@ -3565,7 +3565,11 @@
 
           int status = yyparse ();
 
-          delete global_command;
+          // Use an unwind-protect cleanup function so that the
+          // global_command list will be deleted in the event of an
+          // interrupt.
+
+          frame.add_fcn (cleanup_statement_list, &global_command);
 
           fcn_ptr = primary_fcn_ptr;
 
@@ -4345,6 +4349,14 @@
         {
           if (command_list)
             {
+              unwind_protect inner_frame;
+
+              // Use an unwind-protect cleanup function so that the
+              // global_command list will be deleted in the event of an
+              // interrupt.
+
+              inner_frame.add_fcn (cleanup_statement_list, &command_list);
+
               tree_statement *stmt = 0;
 
               if (command_list->length () == 1
@@ -4381,10 +4393,6 @@
               else
                 error ("eval: invalid use of statement list");
 
-              delete command_list;
-
-              command_list = 0;
-
               if (error_state
                   || tree_return_command::returning
                   || tree_break_command::breaking
@@ -4428,6 +4436,16 @@
   return eval_string (s, silent, parse_status, nargout);
 }
 
+void
+cleanup_statement_list (tree_statement_list **lst)
+{
+  if (*lst)
+    {
+      delete *lst;
+      *lst = 0;
+    }
+}
+
 DEFUN (eval, args, nargout,
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} eval (@var{try}, @var{catch})\n\
--- a/src/parse.h	Thu Dec 01 04:04:50 2011 -0500
+++ b/src/parse.h	Thu Dec 01 04:26:46 2011 -0500
@@ -36,6 +36,7 @@
 class tree;
 class tree_matrix;
 class tree_identifier;
+class tree_statement_list;
 class octave_function;
 
 #include "oct-obj.h"
@@ -113,4 +114,6 @@
 extern OCTINTERP_API octave_value
 eval_string (const std::string&, bool silent, int& parse_status);
 
+extern OCTINTERP_API void cleanup_statement_list (tree_statement_list **lst);
+
 #endif
--- a/src/pt-idx.cc	Thu Dec 01 04:04:50 2011 -0500
+++ b/src/pt-idx.cc	Thu Dec 01 04:26:46 2011 -0500
@@ -113,6 +113,13 @@
       delete *p;
       args.erase (p);
     }
+
+  while (! dyn_field.empty ())
+    {
+      std::list<tree_expression *>::iterator p = dyn_field.begin ();
+      delete *p;
+      dyn_field.erase (p);
+    }
 }
 
 bool
--- a/src/pt-loop.cc	Thu Dec 01 04:04:50 2011 -0500
+++ b/src/pt-loop.cc	Thu Dec 01 04:26:46 2011 -0500
@@ -91,6 +91,7 @@
 
 tree_simple_for_command::~tree_simple_for_command (void)
 {
+  delete lhs;
   delete expr;
   delete maxproc;
   delete list;
@@ -119,6 +120,7 @@
 
 tree_complex_for_command::~tree_complex_for_command (void)
 {
+  delete lhs;
   delete expr;
   delete list;
   delete lead_comm;
--- a/src/toplev.cc	Thu Dec 01 04:04:50 2011 -0500
+++ b/src/toplev.cc	Thu Dec 01 04:26:46 2011 -0500
@@ -571,11 +571,13 @@
             {
               if (global_command)
                 {
-                  global_command->accept (*current_evaluator);
+                  // Use an unwind-protect cleanup function so that the
+                  // global_command list will be deleted in the event of
+                  // an interrupt.
 
-                  delete global_command;
+                  frame.add_fcn (cleanup_statement_list, &global_command);
 
-                  global_command = 0;
+                  global_command->accept (*current_evaluator);
 
                   octave_quit ();