Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
0

Recursive table function causes stack overflow?

Asked by 10 years ago

So I wrote this function to print the contents of a table for debugging purposes. I've tested it in cases that I have generated, but I keep getting stack overflow errors when using it on certain tables (these being ones made by the Roblox Animation Editor, so I don't exactly know their contents hence the function) .

My question is: What could I throw at this to create a stack overflow? I get that excessive recursion could cause this, but I'm not exactly sure how I could achieve that by just traversing tables. I don't believe they're excessively large or anything, but maybe I under estimate what it takes to cause a stack overflow with this.

function DisplayTable(tab, depth) --returns a string representation of a table and it's contents.
    depth = depth and depth + 1 or 1
    local str = ""
    for i,v in pairs(tab) do
        str = str..string.rep("\t", depth)..tostring(v).."\n"
        if type(v) == "table" then
            str = str..DisplayTable(v, depth).."\n"
        end
    end
    if depth == 1 then
        return tostring(tab).."\n"..str --tack the original table at start.
    end
    return str
end

What the output looks like given a fairly normal table:

local t = {
    a = "test",
    1,
    {5,2,5},
    {"b",{1,2,3}},
    {"goback",5,4,3}
}
>
table: 210EC6E0
    1
    table: 210EB9C0
        5
        2
        5

    table: 210EBC90
        b
        table: 210EC650
            1
            2
            3


    table: 210EB150
        goback
        5
        4
        3

    test

1 answer

Log in to vote
1
Answered by
BlueTaslem 18071 Moderation Voter Administrator Community Moderator Super Administrator
10 years ago

Lua has a max recursion limit of 16,000+.

Tables shouldn't be that deep. One possibility would be circular references in tables, for example, something like this:

local one = {};
local two = {};
table.insert(two,one);
table.insert(one,two);

What exactly you want to show for a loop is difficult. One option would be to just stop and show ellipses instead of the table if you've already seen it, or instead refer to a number which is printed at the beginning of each table entry (I implement this here)

I would also make a minor change to your function to make it a little cleaner; make it process all objects and check at the top whether or not it's a table, rather than inside. It cleans it up a bit:

function DisplayTable(tab, depth, visited,numvisited)
    --returns a string representation of a table and its contents.
    visited = visited or {new=1};
    depth = depth and depth + 1 or 1
    local tabs = string.rep("\t",depth - 1);
    local name = tostring(tab);
    if type(tab) == "table" then
        local loop = visited[tab];
        local new = visited.new;
        loop = loop or new;
        visited[tab] = loop;
        name = name .. " {" ..  loop .. "}";
        if loop == new then
            visited.new = new + 1;
        else
            return tabs .. name .. "\n";
        end
    end
    local out = tabs .. name .. "\n";
    if type(tab) == "table" then
        for i,v in ipairs(tab) do
            out = out .. DisplayTable(v, depth + 1, visited);
        end
    end
    return out;
end
0
ah, thanks! I didn't think about circular references like that, for some reason they factored into the problem in my head as just a reference to the table and not it's contents. I'm sure that was the problem. MrgamesNwatch 65 — 10y
Ad

Answer this question