• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!
  • Hello [name]! Thanks for joining the GMC. Before making any posts in the Tech Support forum, can we suggest you read the forum rules? These are simple guidelines that we ask you to follow so that you can get the best help possible for your issue.

weak_ref_create could cause memory leak?

Zhanghua

Member
Ticket #189983

In test object: this would cause a memory leakage.
GML:
//Create Event to define the struct
function a() constructor{ b = 123; }
//Step Event  to loop
if(1){//has memory leak
    c = weak_ref_create( new a() );
}else{//no memory leak
    c = new a();
}
gc_collect();
 
Last edited:

gnysek

Member
You posted some code, but why you think it causes memory leak ? If first "if" uses more memory it might be because GM reserves it, but doesn't mean it uses it. Also, as "c" isn't temporary variable, it won't be removed by gc_collect, but assigned to object. weak_ref uses more memory, as have more data, than your "a()" constructor.
 

Zhanghua

Member
You posted some code, but why you think it causes memory leak ? If first "if" uses more memory it might be because GM reserves it, but doesn't mean it uses it. Also, as "c" isn't temporary variable, it won't be removed by gc_collect, but assigned to object. weak_ref uses more memory, as have more data, than your "a()" constructor.
So, I report it as bug.....
If condition is just for test conveniently....
 
D

Deleted User

Guest
In test object: this would cause a memory leakage.
GML:
//Create Event to define the struct
function a() constructor{ b = 123; }
//Step Event  to loop
if(1){//has memory leak
    c = weak_ref_create( new a() );
}else{//no memory leak
    c = new a();
}
gc_collect();
it is that "gc_collect();" causing it.

comment it out and no memoryleak, tested on gms 2.3.5.589. runtime 2.3.5.458.

the memoryleak is very very very slow, but it is there.


EDIT:
hmmm, it is so slow that it might just be data building up? maybe not a "real" leak? idk.
 

chamaeleon

Member
Store weak refs in an array or ds_list and use a loop put 100 or 1000 into it every step for faster memory usage growth (same 0 to 999 indices, not adding extra to make the array grow continuously). Definitely some leak there.
 

gnysek

Member
OK, so there's assumption, that structs created by weak_ref_create() aren't garbage collected, and executing them every step still keeps old unreferenced values in memory?
 

Zhanghua

Member
OK, so there's assumption, that structs created by weak_ref_create() aren't garbage collected, and executing them every step still keeps old unreferenced values in memory?
Seems the weak_ref can't be garbage collected totally.
 

chamaeleon

Member
My very similar test, showing a fairly steady increase in memory (speeded up by increasing loop size if desired)
Create event
GML:
function foo_struct() constructor { foo = array_create(10000); }
foo = [];
Step event
GML:
for (var i = 0; i < 10; i++) {
    foo[i] = weak_ref_create(new foo_struct()); // memory usage grows, related to weak ref
    //foo[i] = new foo_struct(); // memory usage roughly constant (some bumps up and down, but not growing)
    //array_push(foo, new foo_struct()); // memory usage grows much faster (not getting rid of any structs obviously)
}
If I switch to using the last line in the loop, the memory usage grows much faster because all structs (no weak ref involved) are retained. Because this growth is much faster than when using the weak ref line, it seems that it is not leaking the content of the foo_struct, but it is leaking something related to the weak ref.
 

gnysek

Member
If I switch to using the last line in the loop, the memory usage grows much faster because all structs (no weak ref involved) are retained.
That would have sense:
1) weak refs aren't removed from memory (grows indefinitely?), but structs yes, as they aren't assigned/referenced by any variable
2) we only fill 10 indexes of array every step, so old structs are being GC as they not referenced anymore, while new ones are taking their place
3) this array will grow indefinitely, so memory usage must grow

it seems that weak ref structs are itself also flagged as weak refs :)
 
D

Deleted User

Guest
My very similar test, showing a fairly steady increase in memory (speeded up by increasing loop size if desired)
Create event
GML:
function foo_struct() constructor { foo = array_create(10000); }
foo = [];
Step event
GML:
for (var i = 0; i < 10; i++) {
    foo[i] = weak_ref_create(new foo_struct()); // memory usage grows, related to weak ref
    //foo[i] = new foo_struct(); // memory usage roughly constant (some bumps up and down, but not growing)
    //array_push(foo, new foo_struct()); // memory usage grows much faster (not getting rid of any structs obviously)
}
If I switch to using the last line in the loop, the memory usage grows much faster because all structs (no weak ref involved) are retained. Because this growth is much faster than when using the weak ref line, it seems that it is not leaking the content of the foo_struct, but it is leaking something related to the weak ref.
yeah this example builds the memory a lot faster than the original example from OP.
memory usage builds up around 100mb\sec.

definitely a leak there, tested on gms 2.3.5.589. runtime 2.3.5.458.
 

rwkay

GameMaker Staff
GameMaker Dev.
A weak_ref is just a struct itself (it will get garbage collected as well) the main difference is it will NOT keep the thing it is a weak reference to alive.

If you are remembering the weak_ref's in a struct or data structure then YOU are keeping it (the weak_ref) alive and YOU are causing the memory leak. If you are not keeping them around then there may well be something else going on (i.e. depending on how you are viewing the memory size, Task Manager is not good Debugger etc is the best way.)

Russell
 

chamaeleon

Member
If you are remembering the weak_ref's in a struct or data structure then YOU are keeping it (the weak_ref) alive and YOU are causing the memory leak.
Only a finite number of weak refs are kept every step. Every step the entries in the array in my example is overwritten by new refs, which should let the overwritten refs be garbage collected.

If there was no leak the memory usage should behave the same as if no ref was used. But with refs the usage increases linearly over time, without, just storing a normal struct in the same array, it remains constant on average (just some bumps up and down).
 

Zhanghua

Member
A weak_ref is just a struct itself (it will get garbage collected as well) the main difference is it will NOT keep the thing it is a weak reference to alive.

If you are remembering the weak_ref's in a struct or data structure then YOU are keeping it (the weak_ref) alive and YOU are causing the memory leak. If you are not keeping them around then there may well be something else going on (i.e. depending on how you are viewing the memory size, Task Manager is not good Debugger etc is the best way.)

Russell
Is it a bug?
 

Zhanghua

Member
A weak_ref is just a struct itself (it will get garbage collected as well) the main difference is it will NOT keep the thing it is a weak reference to alive.

If you are remembering the weak_ref's in a struct or data structure then YOU are keeping it (the weak_ref) alive and YOU are causing the memory leak. If you are not keeping them around then there may well be something else going on (i.e. depending on how you are viewing the memory size, Task Manager is not good Debugger etc is the best way.)

Russell
This will have a memory leak too....
And is this a bug?


GML:
//Create
function test() constructor {}
c = weak_ref_create( new test() );

//Step
if( !weak_ref_alive(c) ){
    delete c;
    c = weak_ref_create( new test() );
}
 
Top