Is this true that indexing arrays cause memory leak?

Hey, soo quick question, few months ago i heard that indexing arrays (only numeric indexes) instead of using table library can cause memory leak, example:

local arr = {}
arr[1] = true
arr[2] = false
arr[3] = true

-- code

arr[2] = nil -- memory leak

I use numeric indexes that i remove this way because they are unique per object to store OOP objects, is there any alternative to prevent memory leaks?

arr[2] = nil will set the reference at that position to not exist. So as long as you have properly cleaned up that OOP object it won’t cause any issues

Luau is a memory-safe language; it has it’s own garbage collector. This means you don’t need to worry about leaks from things like these - when the gc detects that something is no longer being used, it will free the allocated memory automatically. Although setting a key to nil might help in terms of speed, it will eventually get cleared when that scope is checked.

This is different to other languages, like C++, where you need to manually free the memory pointer allocated to a variable as they are not memory-safe.

//you have a pointer here
int* pointer;

//you allocate the pointer
pointer = new int;

//you assign it
*pointer = 3;

//you remove it
delete pointer;
1 Like

this is not true. setting an index to nil will always have it stored as nil unless you call table.remove on that index in that case every element past the one you remove will be shifted down.

1 Like

while it’s true other indexes will not be shifted down when one is set to nil, the gc will still clean up the allocated memory. You’ll just have a missing index.

You can actually test this behaviour. I did the following:

local arr = {1, 2, 3}
arr[2] = nil

print(arr) --[[ outputs:
{
    [1] = 1,
    [2] = nil,
    [3] = 3
}

--yes, nil still shows up as an index due to the way Luau handles memory
]]

--but now, try iterating over that array
for i, v in next, arr, nil do
    print(i, v)
end

--[[
this outputs:
1 1
3 3
]]
--as you can see, index 2 was skipped
2 Likes

Allocating things with an instance as an index in a table will block the gc. You need to manually remove those by setting the value to nil

1 Like

yes, but the OP’s question is about arrays, not dictionaries with instance keys.

1 Like

Perhaps do you mean something like this?

local weakArray = {}

weakArray[1] =  true
weakArray[2] = false
weakArray[3] = true

weakArray[2] = nil -- Removing as a library

-- Output current array
warn(weakArray)
output = [[
{
	[1] = true,
	[2] = nil, -- INDEX STILL HERE, NOT THE OBJECT
	[3] = true
}
]]

local weakArray = {}

weakArray[1] =  true
weakArray[2] = false
weakArray[3] = true

table.remove(weakArray, 2) -- Removing as array

-- Output current array
warn(weakArray)
output = [[
{
	[1] = true,
	[2] = true -- INDEX IS NOT IN ARRAY ANYMORE
}
]]

I wont call it a memory leak, but if the indexes in the array are important for certain mechanic, you will find an issue with having the index[2] still existing even if the objects referenced got gc

1 Like

I totally agree, its the same I was saying, but, what if you do this cause you DONT need to iterate whole array to know how many keys are in it:

local arr = {1, 2, 3}
arr[2] = nil

print(#arr) -- OUTPUT 3 indexes unless you do a for iteration
3 Likes

While yes, it is better to use table.remove in cases such as this, it still doesn’t cause a memory leak. (I don’t think table.remove causes a re-hash, so your table would be the same in both cases.)
Setting it to nil would cause holes though. If you know the index, you should always use table.remove, however, keep in mind that table.remove re-orders the table.

2 Likes

Making what you did will convert array into dictionary. That’s because array should have consistant int chain, and # operator will show only (remaining or 0 length - I don’t remember what exactly) Other keys will be able to be retrieved with direct ask, pairs.
This won’t cause any memory leaks, because of gc. If it were causing memory leaks, then EVERY my system will go vroom crash because of how much I utilize this.

1 Like

Indexes are reused, this mean that if new id is generated, if there are ids that existed before but they are in recycled table, then object’s Id will be set to this recycled id, i made tests before but now when studio is down i can’t do them, still thx for help everyone

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.