Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
✓ ANSWER ACCEPTED

Recursive table function causes stack overflow?

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

✓ Accepted answer

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

1 comment

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.

This discussion is preserved as it was. New answers, comments, and votes are closed.