# HG changeset patch # User jwe # Date 1153942068 0 # Node ID e5c0831a48bdc68e4cddf53b627bbde565a76a42 # Parent 80d3933fb8b63aa4cd670e4cb95ecf0e96fc1032 [project @ 2006-07-26 19:27:48 by jwe] diff --git a/src/ChangeLog b/src/ChangeLog --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,5 +1,15 @@ 2006-07-26 John W. Eaton + * mex.cc (xfree): New function. + (mex::free): Use it. + (mxArray_struct::~mxArray_struct, mxArray_cell::~mxArray_cell): + Delete elements with delete, not mxDestroyArray. + (mex::cleanup): Don't call mex::free or mex::free_value. + (mex::free_value): Add debug warning. + (mex::mark, mex::unmark): Fix debug warning. + (call_mex): Use unwind_protect frame. + (mexUnlock): Use iterator to remove item from mex_lock_count. + * octave.cc (maximum_braindamage): Use disable_warning instead of bind_internal_variable to disable function-name-clash warning. * error.cc (disable_warning): No longer static. diff --git a/src/mex.cc b/src/mex.cc --- a/src/mex.cc +++ b/src/mex.cc @@ -29,6 +29,16 @@ // #define DEBUG 1 +static void +xfree (void *ptr) +{ +#ifdef DEBUG + std::cerr << "free: " << ptr << std::endl; +#endif + + ::free (ptr); +} + static int max_str_len (int m, const char **str) { @@ -1518,7 +1528,7 @@ int ntot = nfields * get_number_of_elements (); for (int i = 0; i < ntot; i++) - mxDestroyArray (data[i]); + delete data[i]; mxFree (data); } @@ -1738,7 +1748,7 @@ int nel = get_number_of_elements (); for (int i = 0; i < nel; i++) - mxDestroyArray (data[i]); + delete data[i]; mxFree (data); } @@ -1887,7 +1897,7 @@ ~mex (void) { if (! memlist.empty ()) - error ("mex: cleanup failed"); + error ("mex: %s: cleanup failed", function_name ()); mxFree (fname); } @@ -1915,13 +1925,26 @@ { mex *context = static_cast (ptr); + // We can't use mex::free here because it modifies memlist. for (std::set::iterator p = context->memlist.begin (); p != context->memlist.end (); p++) - context->free (*p); - + { + if (*p) + { + context->unmark (*p); + + xfree (*p); + } + } + + context->memlist.clear (); + + // We can't use mex::free_value here because it modifies arraylist. for (std::set::iterator p = context->arraylist.begin (); p != context->arraylist.end (); p++) - context->free_value (*p); + delete *p; + + context->arraylist.clear (); } // allocate a pointer, and mark it to be freed on exit @@ -1938,7 +1961,7 @@ // FIXME -- could use "octave_new_handler();" instead error ("%s: failed to allocate %d bytes of memory", - mexFunctionName (), n); + function_name (), n); abort (); } @@ -2018,10 +2041,7 @@ { global_memlist.erase (p); -#ifdef DEBUG - std::cerr << "free: " << ptr << std::endl; -#endif - ::free (ptr); + xfree (ptr); } else warning ("mxFree: skipping memory not allocated by mxMalloc, mxCalloc, or mxRealloc"); @@ -2043,8 +2063,17 @@ // Free an array and its contents. void free_value (mxArray *ptr) { - arraylist.erase (ptr); - delete ptr; + std::set::iterator p = arraylist.find (ptr); + + if (p != arraylist.end ()) + { + arraylist.erase (p); + delete ptr; + } +#ifdef DEBUG + else + warning ("mex::free_value: skipping memory not allocated by mex::make_value"); +#endif } // Mark an array and its contents so it will not be freed on exit. @@ -2077,7 +2106,7 @@ { #ifdef DEBUG if (memlist.find (p) != memlist.end ()) - warning ("%s: double registration ignored", mexFunctionName ()); + warning ("%s: double registration ignored", function_name ()); #endif memlist.insert (p); @@ -2085,39 +2114,44 @@ // Unmark a pointer to be freed on exit, either because it was // made persistent, or because it was already freed. - void unmark (void *p) + void unmark (void *ptr) { + std::set::iterator p = memlist.find (ptr); + + if (p != memlist.end ()) + memlist.erase (p); #ifdef DEBUG - if (memlist.find (p) != memlist.end ()) - warning ("%s: value not marked", mexFunctionName ()); + else + warning ("%s: value not marked", function_name ()); #endif - - memlist.erase (p); } // List of memory resources we allocated. static std::set global_memlist; // Mark a pointer as one we allocated. - void global_mark (void *p) + void global_mark (void *ptr) { #ifdef DEBUG - if (global_memlist.find (p) != global_memlist.end ()) - warning ("%s: double registration ignored", mexFunctionName ()); + if (global_memlist.find (ptr) != global_memlist.end ()) + warning ("%s: double registration ignored", function_name ()); #endif - global_memlist.insert (p); + global_memlist.insert (ptr); } // Unmark a pointer as one we allocated. - void global_unmark (void *p) + void global_unmark (void *ptr) { + std::set::iterator p = global_memlist.find (ptr); + + if (p != global_memlist.end ()) + global_memlist.erase (p); #ifdef DEBUG - if (global_memlist.find (p) != global_memlist.end ()) - warning ("%s: value not marked", mexFunctionName ()); + else + warning ("%s: value not marked", function_name ()); #endif - global_memlist.erase (p); } }; @@ -2773,6 +2807,11 @@ for (int i = 0; i < nout; i++) argout[i] = 0; + unwind_protect::begin_frame ("call_mex"); + + // Save old mex pointer. + unwind_protect_ptr (mex_context); + mex context; unwind_protect::add (mex::cleanup, static_cast (&context)); @@ -2780,9 +2819,6 @@ for (int i = 0; i < nargin; i++) argin[i] = context.make_value (args(i)); - // Save old mex pointer. - unwind_protect_ptr (mex_context); - if (setjmp (context.jump) == 0) { mex_context = &context; @@ -2804,9 +2840,6 @@ } } - // Restore old mex pointer. - unwind_protect::run (); - // Convert returned array entries back into octave values. octave_value_list retval; @@ -2832,7 +2865,7 @@ } // Clean up mex resources. - unwind_protect::run (); + unwind_protect::run_frame ("call_mex"); return retval; } @@ -3156,7 +3189,9 @@ { const char *fname = mexFunctionName (); - if (mex_lock_count.find (fname) == mex_lock_count.end ()) + std::map::iterator p = mex_lock_count.find (fname); + + if (p == mex_lock_count.end ()) warning ("mexUnlock: funtion `%s' is not locked", fname); else { @@ -3166,7 +3201,7 @@ { munlock (fname); - mex_lock_count.erase (fname); + mex_lock_count.erase (p); } } }