GMS 2 creating ds_list via script causes memory leak?

Discussion in 'Programming' started by 31Nf4ChZ4H73N, Sep 13, 2019.

  1. 31Nf4ChZ4H73N

    31Nf4ChZ4H73N Member

    Joined:
    Jul 6, 2016
    Posts:
    21
    When I create as ds_list and store it in a local variable in a script which returns this value does this cause a memory leak?
    example:
    script: createMyList
    Code:
    var myList = ds_list_create();
    return myList;

    objectList
    StepEvent
    Code:
    if(mouse_check_button_pressed(mb_left))
    {
    list = createmyList();
    }
     
  2. chamaeleon

    chamaeleon Member

    Joined:
    Jun 21, 2016
    Posts:
    954
    You have a memory leak because none of your code shows a ds_list_destroy().. Joking aside, no, you don't have a leak from the use of that local variable, as long as you have code somewhere whose responsibility it is to destroy it when no longer needed. Since you're unsure about this, let me reinforce the fact that the return value from the various data structure creation functions is simply an integer, with no inherent meaning whatsoever. The only meaning for it is derived from calling a data structure function with it as the reference to the data structure. There is no hidden meaning associated with the variable (be it local, global, or instance) just because it happened to be returned by any of the data structure create functions. In other words, when you call a data structure function it will assume the number you pass in references a data structure of the type the function works with. When you assign, return, perform mathematical calculations with it (unlikely), it's just a number.
     
    31Nf4ChZ4H73N likes this.
  3. FrostyCat

    FrostyCat Member

    Joined:
    Jun 26, 2016
    Posts:
    4,470
    It will cause a memory leak if the target receiving the returned value doesn't clean after it (in this case using ds_list_destroy()), or if it returned to nowhere. Your example would leak on every click past the first.
     
    ParodyKnaveBob and 31Nf4ChZ4H73N like this.
  4. 31Nf4ChZ4H73N

    31Nf4ChZ4H73N Member

    Joined:
    Jul 6, 2016
    Posts:
    21
    I'm sorry I am not quite shure if I understand this.

    So, if I implement something like this
    destroy event:
    Code:
    ds_list_destroy(list);
    
    does every mouse click still create a memory leak because the script in which the ds_list gets created doesnt overwrite the current ds list?

    so should I do something like this, too, in order to prevent memory leak creation?
    step event of the objectList:
    Code:
    if(mouse_check_button_pressed(mb_left))
    {
     if(ds_exists(list,ds_list))
     {
      ds_list_destroy(list);
     }
     list = createmyList();
    }
    
    sorry that the code is all in one height somehow the indent doesnt move the code to the right but just writes [ INDENT]
     
    ParodyKnaveBob likes this.
  5. TsukaYuriko

    TsukaYuriko Q&A Spawn Camper Forum Staff Moderator

    Joined:
    Apr 21, 2016
    Posts:
    1,589
    Indentation in code blocks works based on spaces or tabs, not based on the INDENT BBcode.

    A memory leak will occur if the amount of calls to ds_list_destroy is not equal to the amount of calls to ds_list_create over the lifetime of an instance of this object.

    Either destroy or empty this list before it is recreated, if recreating it once in a while is necessary, or don't recreate it if it already exists.
     
    ParodyKnaveBob likes this.
  6. FrostyCat

    FrostyCat Member

    Joined:
    Jun 26, 2016
    Posts:
    4,470
    Two things:
    • Never use the Destroy event to clean after data structures or other ID-indexed resources. Changing rooms does not trigger the Destroy event, so you will leak the instant you go to another room. Always use the Cleanup event.
    • When you call list = createmyList(); repeatedly, all you are doing is pointing the same variable to a different list on each call. You are not overwriting the lists themselves or cleaning them up. You will still leak on every call past the first.
    ds_exists() is not capable of forgiving references to undeclared variables. You still have to declare list ahead of time.

    Create:
    Code:
    list = ds_list_create();
    Step:
    Code:
    if (mouse_check_button_pressed(mb_left))
    {
        ds_list_destroy(list);
        list = createmyList();
    }
    
    Cleanup:
    Code:
    ds_list_destroy(list);
    Alternatively, change the script so that instead of creating a new list, it takes a list and clears and writes to it.
    Code:
    ///@func writeMyList(list)
    ds_list_clear(argument0);
    /* Write to the list at argument0 here */
    
    Create:
    Code:
    list = ds_list_create();
    Step:
    Code:
    if (mouse_check_button_pressed(mb_left))
    {
        writeMyList(list);
    }
    
    Cleanup:
    Code:
    ds_list_destroy(list);
     
  7. NightFrost

    NightFrost Member

    Joined:
    Jun 24, 2016
    Posts:
    1,926
    A ds list is basically a memory allocation. If you don't destroy the old list, it will still exist after you've created a new one, all you'd be doing was saving the pointer to the new list over the old to the list variable. It would be good to destroy the list as soon as its use is over, but we don't know how you've implemented your code. Another alternative would be to define the list in Create event and just repopulate it on mouseclick, but again we don't know your implementation and how well this might suit it.
     
    ParodyKnaveBob and 31Nf4ChZ4H73N like this.
  8. 31Nf4ChZ4H73N

    31Nf4ChZ4H73N Member

    Joined:
    Jul 6, 2016
    Posts:
    21
    Thank you very much. I will rewrite my code and then set this thread to solved. Hopefully this will fix the memory leak.

    However, there is another bug which might be related to this memory leak. I am not shure if this ok to post it into this thread but I think this might be somehow related. If not I will create a new thread.


    In my current project I run into a really weird error. I run into this issue when reading out data from a ds_list. Suddenly the value is not a number anymore but a string value. A string value which I actually have stored in a different anmed ds_list! Does this maybe relate to the memory leak? That maybe that because so many ds_list get created and not cleared/deleted that the pointer gets somehow confused or something?
     
    ParodyKnaveBob likes this.
  9. TsukaYuriko

    TsukaYuriko Q&A Spawn Camper Forum Staff Moderator

    Joined:
    Apr 21, 2016
    Posts:
    1,589
    Data structure handles are numbers, not pointers. They don't point to memory, but to a position in a list of data structures of the respective types.

    If any data structure is destroyed, its ID gets re-used when new data structures are created. A lack of proper data structure reference management - especially when referring to the same data structure from multiple places - can therefore lead to two inherently different variables pointing to the same data structure.
     
    ParodyKnaveBob likes this.
  10. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,800
    To clarify, suppose you have

    mainlist=ds_list_create();
    otherlist=ds_list_create();

    So mainlist has a value of 0 and otherlist has a value of 1. If you destroy otherlist and create a new one, the new value of otherlist will be 2.

    Then let's say somewhere in another object you create a new variable (let's call it newlist) and set it to a default value of 0. Even though you havenot yet assigned a list to newlist, it still points to a valid list -- list 0, which is mainlist.

    Another possibility is if you accidentally set otherlist to a value of 0 directly. Then otherlist will be pointing to the same list as mainlist.
     
    ParodyKnaveBob likes this.
  11. 31Nf4ChZ4H73N

    31Nf4ChZ4H73N Member

    Joined:
    Jul 6, 2016
    Posts:
    21
    First of all thank you very much for your help!
    Here is a little update just in cases if somebody runs into a similar problem and reads this thread:
    I have not mentioned it before but I used a json file for the data and used this code
    objectData:
    Code:
    myData = return json_decode(@'
    {
       "player" : {
            "name"            : "Player",
            "hp"        : 2
        },
        "enemy" : {
            "name"          : "Enemy",
            "hp"        : 2
        }
    }');
    As I understood myData is a ds_map and contains two ds_list.
    Apparently when I copy a ds_list out of the ds_map myData to a new variable and delete it I also delete the ds_list into the myData ds_map. One can see this using the debugger and then looking for the value assigned to them.
    This trick can be used to avoid creating a reference but create a new copy of the ds_list. (Btw I didnt came up with but I saw it in a Udemy Tutorial for GM 1.4 by Benjamin Anderson)
    objectPlayer:
    Code:
    var playerData = json_decode(json_encode(oData.myData[? "player"]));
    playerName = playerData[? "name"];
    playerHP = playerData[? "hp"];
    ds_map_destroy(playerData);
    
     
  12. 31Nf4ChZ4H73N

    31Nf4ChZ4H73N Member

    Joined:
    Jul 6, 2016
    Posts:
    21
    game_restart() does not trigger the Destroy event, too?

    What exactly does the cleanup event? When or what triggers it? (couldnt find it in the manual via search)
     
  13. FrostyCat

    FrostyCat Member

    Joined:
    Jun 26, 2016
    Posts:
    4,470
    Only instance_destroy() and position_destroy() trigger the Destroy event. Everything that can cause an instance to stop existing, including room changes, game restarts and of course instance_destroy() and position_destroy(), will trigger the Cleanup event.
     
    ParodyKnaveBob likes this.
  14. rIKmAN

    rIKmAN Member

    Joined:
    Sep 6, 2016
    Posts:
    4,453
    ParodyKnaveBob likes this.
  15. 31Nf4ChZ4H73N

    31Nf4ChZ4H73N Member

    Joined:
    Jul 6, 2016
    Posts:
    21

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice