# HG changeset patch # User John W. Eaton # Date 1504908950 14400 # Node ID ef85638c605a056cc6c265fc1081b24feec10e25 # Parent ec3d37eeafa25ddbfc1d7d099d25b9833d38b5b2 also cache parent_function in symbol_table scope Inside a symbol table scope, we currently store a pointer to the parent scope (if it exists), but this is not sufficient to prevent the parent scope from being deleted. For example, this can happen when a function that contains an anonymous function definition is deleted. If the anonymous function remains accessible, then resolving any symbols that it references may fail when it is called. Caching the parent function avoids this problem as it increments the reference count for the function, and that will prevent the scope object from being deleted. * symtab.cc (symbol_table::scope::set_parent): Also cache parent function if it exists. * symtab.h (symbol_table::scope::m_parent): New data member. (symbol_table::scope::parent_fcn): New function. (symbol_table::scope::dup): Also copy m_parent_fcn. diff -r ec3d37eeafa2 -r ef85638c605a libinterp/corefcn/symtab.cc --- a/libinterp/corefcn/symtab.cc Thu Aug 31 21:10:56 2017 +0200 +++ b/libinterp/corefcn/symtab.cc Fri Sep 08 18:15:50 2017 -0400 @@ -1803,6 +1803,23 @@ } void + symbol_table::scope::set_parent (scope *p) + { + m_parent = p; + + if (m_parent) + { + // If m_parent is the top-level scope, there will be no parent + // function. + + octave_function *ov_fcn = m_parent->function (); + + if (ov_fcn) + m_parent_fcn = octave_value (ov_fcn, true); + } + } + + void symbol_table::scope::update_nest (void) { if (m_parent) diff -r ec3d37eeafa2 -r ef85638c605a libinterp/corefcn/symtab.h --- a/libinterp/corefcn/symtab.h Thu Aug 31 21:10:56 2017 +0200 +++ b/libinterp/corefcn/symtab.h Fri Sep 08 18:15:50 2017 -0400 @@ -1567,7 +1567,7 @@ scope (const std::string& name = "") : m_name (name), m_symbols (), m_persistent_symbols (), m_subfunctions (), - m_fcn (nullptr), m_parent (nullptr), m_children (), m_is_nested (false), + m_fcn (nullptr), m_parent (nullptr), m_parent_fcn (), m_children (), m_is_nested (false), m_is_static (false), m_context (0) { } @@ -1593,6 +1593,7 @@ void mark_static (void) { m_is_static = true; } scope * parent_scope (void) const { return m_parent; } + octave_value parent_fcn (void) const { return m_parent_fcn; } scope * dup (void) const { @@ -1602,6 +1603,7 @@ new_sid->insert_symbol_record (nm_sr.second.dup (new_sid)); new_sid->m_parent = m_parent; + new_sid->m_parent_fcn = m_parent_fcn; return new_sid; } @@ -2034,7 +2036,7 @@ void set_function (octave_user_function *fcn) { m_fcn = fcn; } - void set_parent (scope *p) { m_parent = p; } + void set_parent (scope *p); void update_nest (void); @@ -2061,6 +2063,7 @@ // Parent of nested function (may be null). scope *m_parent; + octave_value m_parent_fcn; // Child nested functions. std::vector m_children;