octave-maintainers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Crash when clearing "ans" variable in symbol table


From: John W. Eaton
Subject: Re: Crash when clearing "ans" variable in symbol table
Date: Mon, 14 Jan 2008 16:54:32 -0500

On 14-Jan-2008, Michael Goffioul wrote:

| On 1/14/08, John W. Eaton <address@hidden> wrote:
| > Objects are pushed on the value_stack when functions are called
| > recursively.  My guess is that you've found some way to have a
| > recursive call that doesn't properly trigger the push, but still has a
| > pop of the stack.
| 
| Will you have a look into this? Or could you give me some hints
| where to look (I currently have no clue).
| [Note that this is not my code; I just found the problem while testing
| someone else's code; I have no more clues about the offending code]

Please try the following patch.

I think the problem is that "ans" is being added to the symbol table
in a recursive call, so the size of its value_stack is not equal to
the depth of the recursion.  The following patch addresses this by
removing symbols from the table when their value_stack becomes empty.

I think a simple test case is

  function foo (n)
    if (n > 0)
      n
      ans_exists = exist ("ans", "var")  # should be 0.
      foo (n-1);
      ans_exists = exist ("ans", "var")  # should be 0.
    else
      ans_exists = exist ("ans", "var")  # should be 0.
      eval ("13;");
      ans_exists = exist ("ans", "var")  # should be 1.
    endif
  endfunction

Try running this with something like

  foo (3)

With the patch it should only have ans in the deepest of the
recursive calls to foo.  Without it, Octave should crash.

Hey Sergei, here is a chance for you to help us out by creating some
tests.

Thanks,

jwe


2008-01-14  John W. Eaton  <address@hidden>

        * symtab.h (symbol_table::do_pop_context): Remove symbol_records
        which have no more context.
        (symbol_table::symbol_record::pop_context,
        (symbol_table::symbol_record::symbol_record_rep::pop_context):
        Return size of value_stack, or 1 if variable is persistent or global.


Index: src/symtab.h
===================================================================
RCS file: /cvs/octave/src/symtab.h,v
retrieving revision 1.94
diff -u -u -r1.94 symtab.h
--- src/symtab.h        4 Jan 2008 20:26:26 -0000       1.94
+++ src/symtab.h        14 Jan 2008 21:38:28 -0000
@@ -93,7 +93,11 @@
 
       void push_context (void) { value_stack.push (octave_value ()); }
 
-      void pop_context (void) { value_stack.pop (); }
+      size_t pop_context (void)
+      {
+       value_stack.pop ();
+       return value_stack.size ();
+      }
 
       void clear (void)
       {
@@ -254,10 +258,23 @@
        rep->push_context ();
     }
 
-    void pop_context (void)
+    // If pop_context returns 0, we are out of values and this element
+    // of the symbol table should be deleted.  This can happen for
+    // functions like
+    //
+    //   function foo (n)
+    //     if (n > 0)
+    //       foo (n-1);
+    //     else
+    //       eval ("x = 1");
+    //     endif
+    //   endfunction
+    //
+    // Here, X should only exist in the final stack frame.
+
+    size_t pop_context (void)
     {
-      if (! (is_persistent () || is_global ()))
-       rep->pop_context ();
+      return (is_persistent () || is_global ()) ? 1 : rep->pop_context ();
     }
 
     void clear (void) { rep->clear (); }
@@ -1618,8 +1635,13 @@
 
   void do_pop_context (void)
   {
-    for (table_iterator p = table.begin (); p != table.end (); p++)
-      p->second.pop_context ();
+    for (table_iterator p = table.begin (); p != table.end (); )
+      {
+       if (p->second.pop_context () == 0)
+         table.erase (p++);
+       else
+         p++;
+      }
   }
 
   void do_clear_variables (void)

reply via email to

[Prev in Thread] Current Thread [Next in Thread]