• 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.

SOLVED Debug Message of Structs causes Crash

P

Potatoverse

Guest
I'm working on something using structs instead of objects because I'll need a ton of them. One functionality that I want these structs to have is for them to have an inventory and for them to be able to receive input from other structs and give output to other structs.
What I did to achieve that is to make the structs have these variables where in1 and out1 are supposed to be the ids of the respective structs.

It works (almost) fine the way I have it set up but as soon as I try to use show_debug_message and a for loop to check the contents of all the structs it simply crashes as soon as it's supposed to show the debug message of a struct that contains the id of another struct. The crash doesn't produce an error message though.

I'm not even sure whether the variable contains the id of the struct or the struct itself which is why I tried to make that debug message work in the first place.

Here's how I set up my constructor:

GML:
function Unit(_x, _y) constructor{
    randomize();
    sprite_index = sStorageUnit;
    x = _x;
    y = _y;
    transpeed = random_range(0.1, 2);
   
    storage = 100;
    inventory = [10];
    space = function() {
        _space = 0;
        for(var i=0;i<array_length(inventory);i++) {
            _space += inventory[i];
        }
        return _space/storage; // Returns how much space is used / how much space is left
    }
   
    in1 = false;
    out1 = false;
}
And here's the code responsible for assigning the structs to each other:

GML:
if(mouse_check_button_pressed(mb_left) and global.settings.portmode) {
    if(_selection == 0) {
        for(i=0;i<array_length(units);i++) {
            if(mouse_x > units[i].x and mouse_x < units[i].x + 32 and mouse_y > units[i].y and mouse_y < units[i].x + 32 and units[i].out1 == 0) {
                show_debug_message("OK1");
                _selection = units[i];
                break;
            }
        }
    }
    else {
        for(i=0;i<array_length(units);i++) {
            if(mouse_x > units[i].x and mouse_x < units[i].x + 32 and mouse_y > units[i].y and mouse_y < units[i].x + 32 and units[i].in1 == 0 and units[i] != _selection) {
                show_debug_message("OK2");
                _selection.out1 = units[i];
                units[i].in1 = _selection;
                delete _selection;
                _selection = 0;
                break;
            }
        }
    }
}

To put it into words:
1. Check if a unit was clicked and if that unit already has been assigned
2. Save the id of that unit temporarily in _selection
3. Check if another unit was clicked and if that unit is a valid unit
4. Set the respective variables and reset _selection

And here's the simple code that's supposed to give me a debug message:

GML:
for(i=0;i<array_length(units);i++) {
    show_debug_message(string(units[i]));
}
All I get from the console when the crash happens is:
Code:
X://windows/Runner.exe exited with non-zero status (-1073741571)
elapsed time 00:00:18.8512829s for command "[my directory]/GameMakerStudio2/Cache/runtimes\runtime-2.3.0.401/bin/Igor.exe" -j=8 -options="[my directory]\GameMakerStudio2\GMS2TEMP\build.bff" -v -- Windows Run started at 03/26/2021 04:16:38
"cmd"  /c subst Z: /d

elapsed time 00:00:00.0668208s for command "cmd" /c subst Z: /d started at 03/26/2021 04:16:57
"cmd"  /c subst Y: /d

elapsed time 00:00:00.0628323s for command "cmd" /c subst Y: /d started at 03/26/2021 04:16:57
"cmd"  /c subst X: /d

elapsed time 00:00:00.0619867s for command "cmd" /c subst X: /d started at 03/26/2021 04:16:57
FAILED: Run Program Complete
For the details of why this build failed, please review the whole log above and also see your Compile Errors window.
But the Compile Errors window is empty.

I'm sorry if either my code or my writing has been bodged together but I'm really tired right now and just want to post this to get it over with. Thanks for reading.
 

FrostyCat

Redemption Seeker
Structs are not ID-based, they are a first-order type the way arrays also are. If you have any circular references in a unit (e.g. unit A refers to unit B and vice versa), trying to string it is an infinite recursion. This is one situation where the only safe way to directly visualize such a structure is with the debugger.
 
P

Potatoverse

Guest
Structs are not ID-based, they are a first-order type the way arrays also are. If you have any circular references in a unit (e.g. unit A refers to unit B and vice versa), trying to string it is an infinite recursion. This is one situation where the only safe way to directly visualize such a structure is with the debugger.
I thought I heard structs had their own IDs somewhere before. I guess I'll have to start using the debugger now. Thanks a lot!
 

Roldy

Member
To demonstrate @FrostyCat post, the following code is all you need in an empty project to cause a crash and run out of memory.

GML:
function someStruct() constructor{

    in1 = false;

}


var _a = new someStruct();
var _b = new someStruct();


_a.in1 = _b;
_b.in1 = _a;


show_debug_message(string(_a));  // This line creates a string of 'infinite' length (crash will occurr when out of memory)

I thought I heard structs had their own IDs somewhere before. I guess I'll have to start using the debugger now. Thanks a lot!
A way around this is instead of storing a direct reference to the structs, store the index into your Units array instead

example:

GML:
// Instead of
_selection = units[i];

// store the index instead
_selection = i;

//Instead of the following
_selection.out1 = units[i];
units[i].in1 = _selection;
delete _selection;

//Write it this way
units[_selection].out = i;
unit[i].in1 = _selection;
delete units[_selection];

etc...
 
Last edited:
Top