How to prevent out-of-memory crash?

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

How to prevent out-of-memory crash?

Jon Kleiser-2
I've just written a Lua function (below) that returns a textual
representation of "any" Lua object, incl. tables and nested tables. It
works quite fine. My only dissatisfaction with it, is that it quickly uses
up all of memory in case the table you feed into it contains any circular
references, which is not very surprising, since it works recursively. Are
there any easy ways to detect a situation like that before the crash is a
fact?


function asText(obj, asIndex)
   -- Returns a textual representation of "any" Lua object,
   -- incl. tables (and nested tables).
   -- Tables with circular references will cause a crash!
   -- Functions are not decompiled (of course).
   -- Try: print(asText({{"a", "b"}; c=3}))

   if type(obj) == "table" then
      local begBrac, endBrac
      if asIndex then
         begBrac, endBrac = "[{", "}]"
      else
         begBrac, endBrac = "{", "}"
      end
      local t = begBrac
      local k, v = nil, nil
      repeat
         k, v = next(obj, k)
         if k ~= nil then
            if t > begBrac then
               t = t..", "
            end
            t = t..asText(k, 1).."="..asText(v)
         end
      until k == nil
      return t..endBrac
   else
      if asIndex then
         -- we're on the left side of an "="
         if type(obj) == "string" then
            return obj
         else
            return "["..obj.."]"
         end
      else
         -- we're on the right side of an "="
         if type(obj) == "string" then
            return '"'..obj..'"'
         else
            return tostring(obj)
         end
      end
   end
end -- asText

------------

Sincerely,

Jon Kleiser


Reply | Threaded
Open this post in threaded view
|

Re: How to prevent out-of-memory crash?

David Jeske-2
On Fri, Dec 11, 1998 at 04:46:09PM -0200, Jon Kleiser wrote:
> I've just written a Lua function (below) that returns a textual
> representation of "any" Lua object, incl. tables and nested tables. It
> works quite fine. My only dissatisfaction with it, is that it quickly uses
> up all of memory in case the table you feed into it contains any circular
> references, which is not very surprising, since it works recursively. Are
> there any easy ways to detect a situation like that before the crash is a
> fact?

You need to keep track of all the unique object's you've written
out. Steve Dekorte wrote some code which walks a tree, assigns all
nodes unique IDs, persists out the nodes, and persists out the
links. I don't know how applicable his code would be, but the strategy
is pretty straightforward.

You can use tables as indicies as well as values, so keeping track of
the uniqueness isn't too hard. However, in order to be able to
'recreate' the links afterwords, you're best off loading the table as
a flattened list of tables.

For example, if you did this:
  a = {
        b = {
            c = {  d = 1  },
            e = {  f -> b }    -- this is my hokey syntax for a link
            }
      };

Then how would you actually assign f to "b" when you were recreating
the tree? The way I see it, you have two choices:

1) You store a flattened list of tables like this:

flattened_tables = {
    @tbl_a = { b = @tbl_b }
    @tbl_b = { c = @tbl_c }
    @tbl_c = { d = 1 }
    @tbl_e = { f = @tbl_b }
}

Where the "@<tablename>" represents some table pointer which is not
resolved yet. It could be an integer, but it should be tagged
differently, so you don't confuse it with a real integer in the next
step. 

After you loaded the above data, then you would then 'rehyrdate' the
links by replacing each link on the right with the appropriate link on
the left. 

Then all you have to do is grab ahold of the 'root' of the tree, and
throw away the 'flattened_tables' table.
                
2) You could just do a 'hack' which would make a table contain
self-references for any duplicated tables. In this strategy, your
persisted version of the above table might look something like:

 a = {
        b = {
            c = {  d = 1  },
            e = {  f = a.b }    -- this is my link
            }
      };

Except that in your current asText, you don't know the 'name' of the
top-level table.

-- 
David Jeske (N9LCA) + http://www.chat.net/~jeske/ + [hidden email]