GMS 2.3+ Can't Avoid Memory Leak

Scienitive

Member
I'm trying to write a function that does the same thing with instance_place_list() but not with one object with an array of objects.

Here is the function:
GML:
function instance_place_list_ext(_x, _y, _array, _order, _returnarray) {
    var return_count = 0;
    
    var i = 0;
    repeat (array_length(_array)){
        var list = ds_list_create();
        var count = instance_place_list(_x, _y, _array[i], list, _order);
        
        var a = 0;
        repeat (ds_list_size(list)) {
            ds_list_add(_returnarray[0], list[| a]);
            a++;
        }
        ds_list_destroy(list);
        
        return_count += count;
        i++;
    }
    
    _returnarray[1] = return_count;

    return _returnarray;
}
And here is the part of code that i call function:
Code:
var dynamic_list = ds_list_create();
var dynamic_array = [dynamic_list];
dynamic_array = instance_place_list_ext(x, y + sign(vsp), dynamic_objects, false, dynamic_array);
var dynamic_count = dynamic_array[1];
.
.
.
ds_list_destroy(dynamic_list);
My code is working as I expected but there is a problem.
I'm destroying all the lists that I use but I still end up with memory leak. My memory usage always increases when this code runs.
What am I missing?
 

TsukaYuriko

☄️
Forum Staff
Moderator
Does memory usage increase indefinitely? As in, if you run this in an infinite loop, does the game end up crashing with an out of memory error? Memory not instantly being freed is normal, and it may stay committed and will be re-used by the process for a while after being freed.
 

Scienitive

Member
Does memory usage increase indefinitely? As in, if you run this in an infinite loop, does the game end up crashing with an out of memory error? Memory not instantly being freed is normal, and it may stay committed and will be re-used by the process for a while after being freed.
This code runs when the player collides with a dynamic object. So if player stands on a dynamic object this code will run every step. When I do that in debugger mode my memory usage increasing indefinitely but slowly so probably game will end up crashing but it will took a lot time I guess.
 

Scienitive

Member
I put the code in infinite loop but I guess its still not increasing that fast to crash the game, in 2-3 minutes memory usage came 200mb.

It normally works on like 3mb.
 
Hi @Scienitive,
I noticed the function is copying _returnarray when you assign the return_count without the "@" accessor. Can you try accessing with @ and see if that improves memory performance? The garbage collector might be waiting to delete these as @TsukaYuriko mentioned.

Edit: Perhaps you may want to pass the returnlist directly, and return just the count? Then you could get rid of dynamic array allocation altogether unless there's a greater purpose for it in your code.
 
Last edited:

Roldy

Member
FYI I Just made a new project and copied your function.

Made a couple objects. Put several of them in a room.

One of the objects runs your function 10000 times each frame, with a dynamic_objects array filled with the other 2 objects [Object1, Object2];

I see no memory leak.

Potentially your memory leak is caused from some other code in your project, or from the code you omitted to post.

I would suggest doing what I just described, and see if you can reproduce this in a new project using your function. If you can then submit a bug report with that project.

If you cannot then you know you need to look elsewhere for your memory leak.
 
I apologize, admittedly I don't know much about GMS2 at all, but for this code

GML:
var dynamic_list = ds_list_create();
var dynamic_array = [dynamic_list];
dynamic_array = instance_place_list_ext(x, y + sign(vsp), dynamic_objects, false, dynamic_array);
Could it be that dynamic_list is being copied to dynamic_array, and then when you re-assign dynamic_array, the list that was contained in it is being leaked?
 

Scienitive

Member
Hi @Scienitive,
I noticed the function is copying _returnarray when you assign the return_count without the "@" accessor. Can you try accessing with @ and see if that improves memory performance? The garbage collector might be waiting to delete these as @TsukaYuriko mentioned.

Edit: Perhaps you may want to pass the returnlist directly, and return just the count? Then you could get rid of dynamic array allocation altogether unless there's a greater purpose for it in your code.
I get rid of the array and made something like this:
GML:
function instance_place_list_ext(_x, _y, _array, _list, _order) {
    var i = 0;
    repeat (array_length(_array)){
        var list = ds_list_create();
        instance_place_list(_x, _y, _array[i], list, _order);
        
        var a = 0;
        repeat (ds_list_size(list)) {
            ds_list_add(_list, list[| a]);
            a++;
        }
        ds_list_destroy(list);
        i++;
    }

    return _list;
}
Code:
var dynamic_list = ds_list_create();
dynamic_list = instance_place_list_ext(x, y + sign(vsp), dynamic_objects, dynamic_list, false);
var dynamic_count = ds_list_size(dynamic_list);
.
.
.
ds_list_destroy(dynamic_list);
But the problem still goes on.
 

Scienitive

Member
FYI I Just made a new project and copied your function.

Made a couple objects. Put several of them in a room.

One of the objects runs your function 10000 times each frame, with a dynamic_objects array filled with the other 2 objects [Object1, Object2];

I see no memory leak.

Potentially your memory leak is caused from some other code in your project, or from the code you omitted to post.

I would suggest doing what I just described, and see if you can reproduce this in a new project using your function. If you can then submit a bug report with that project.

If you cannot then you know you need to look elsewhere for your memory leak.
I'm actually pretty sure that the memory leak is in the function or my way of calling the function because I was using built-in instance_place_list() before and I didn't have memory leak. But I'm gonna make a new project and test it too.
 

Scienitive

Member
I apologize, admittedly I don't know much about GMS2 at all, but for this code

GML:
var dynamic_list = ds_list_create();
var dynamic_array = [dynamic_list];
dynamic_array = instance_place_list_ext(x, y + sign(vsp), dynamic_objects, false, dynamic_array);
Could it be that dynamic_list is being copied to dynamic_array, and then when you re-assign dynamic_array, the list that was contained in it is being leaked?
It looks like it's not about it, I completely removed dynamic_array from the code but the problem still goes on.
 
I'm actually pretty sure that the memory leak is in the function or my way of calling the function because I was using built-in instance_place_list() before and I didn't have memory leak. But I'm gonna make a new project and test it too.
I did the same test as @Roldy and can confirm there's no memory leak with this code too. Memory rises and falls between 22 and 40mb.

With the first suggestion I made, it cuts it in half, and with the second, it stays steadily at 3mb.

Here's the code from the last test for reference:
Function
GML:
function instance_place_list_ext(_x, _y, _array, _order, _returnlist) {
    var return_count = 0;

    var i = 0;
    repeat (array_length(_array)){
        var list = ds_list_create();
        var count = instance_place_list(_x, _y, _array[i], list, _order);
 
        var a = 0;
        repeat (ds_list_size(list)) {
            ds_list_add(_returnlist, list[| a]);
            a++;
        }
        ds_list_destroy(list);
 
        return_count += count;
        i++;
    }

    return return_count;
}
Step event of test object:
GML:
repeat(10000)
{
    var dynamic_list = ds_list_create();
    var count = instance_place_list_ext(x, y, dynamic_objects, false, dynamic_list);


    ds_list_destroy(dynamic_list);
}
(edit: there's 4 objects in the dynamic_objects array, and 5 instances of this test object in the room)

I think the leak or memory performance issue might be coming from elsewhere as Roldy suggested.
 
Last edited:

Roldy

Member
@Roldy @tadashibashi
I tested and get the same results with you and you were right it wasn't the function or the way i call it. The problem was some other code that relate to this code. I solved the problem, thank you all for your helps.
Your hunches and intuition are important and useful tools for a programmer to isolate bugs. But you always need to find a way to verify them for sure, as quickly as possible. Otherwise you can waste alot of time looking in the wrong spot. A lesson I have learned the hard way.
 
Top