It's Interesting and odd to read the comments about GM and compare them to the framework I've evolved for my own use.
I started with a lot of pointer based dynamically allocated structures of the type Brigand evidently prefers - but discovered that most of the central elements of the game (actors and events and the schedule and the map) need to have many references to each other, in places that depend on the semantics of individual subtypes of those classes - so deallocating anything WITHOUT leaving references to it somewhere is very difficult and gets more difficult the more different kinds of things you have. You wind up having to walk virtually the full game's data structure deleting references every time you want to delete anything. Otherwise, you wind up with dynamically allocated data containing references to deallocated things. If your references happen to be pointers, that's bad for two reasons, because there are two different kinds of bugs it can cause when you try to refer to the object the stale pointer points at. First, you can crash, which is bad, but you can also wind up referring to things allocated after the things the original pointers pointed at were deallocated, which is worse. Also, pointers were an extra headache for save-and-restore functionality, because you had to swizzle all the pointers to get a restored game where the pointers mean the same thing as the pointers in the saved game did.
So I eventually abstracted dynamic allocation, using a manager class for each data type. Now when I say New_Actor(), the manager for actors decides where it's going to keep the new actor and returns a reftype. The manager handles allocation, and keeps a pointer (the ONLY pointer to that actor to live in a dynamically-allocated data type) in a hash table keyed by the reftype value. A reftype value, unlike a pointer value, is never reused, so I don't have to worry about aliasing. I can deallocate on command, without worrying about crashes caused by following stale pointers. When something hands the manager a stale reftype, it returns a null value without crashing, which can be checked for and handled at the call site. Finally reftypes mean the same thing in a restored game that they meant in the saved game with no need for pointer swizzling; the new pointer value, whatever it is, is keyed by the same reftype value inside the actor manager, so the rest of the code, which handles data structures that contain only reftypes, never pointers, need never worry about it.
There's no "maximum number of actors," nor "vast amounts of wasted space", both because the data managers do dynamically resize the hash tables at need. This also takes care of "compacting the array", and does not require walking data structures changing reftypes stored in game data to refer to new array locations when it happens. The complexity cost is an O(1) hash table lookup whenever a routine needs to acquire an actual pointer to data, and that has not been a noticeable burden.
Anyway, the rules are simple. In any dynamically allocated data, you store reftypes rather than pointers. When you actually need a pointer, you use the reftype to look it up. Any time you use a reftype to look up a pointer, you check to see whether the pointer is NULL. If it is, that datum no longer exists.
And, um, underneath it all.... the data manager classes use hash tables which are implemented in terms of arrays. Which are what GM uses.... and what annoys Brigand.
One man's drink is another man's poison?
What your saying may be true, but the conversation stops for me at "need to have many references to each other". As you say, as soon as you start placing pointers everywhere, you end up with memory leaks - you get circular references that don't get garbage collected but you cant reference, stale references that are pointing at some object that is now out of scope - the object continues to exist because "something" is pointing at it, or the most fun bug to track down, the null pointer reference (which is admittedly hard to debug in dynamically allocated system, so that it a point for doing it with arrays).
deallocating anything WITHOUT leaving references to it somewhere is very difficult and gets more difficult the more different kinds of things you have
I keep it simple - items/inventory instances point at/are pointed at by an actor or a SINGLE map manager (for items laying on the ground) and that's it - the destructor for the actor simply points the item objects back at the map manager (the items fall to the ground) which also makes it easy to determine what gets displayed. Actors are in an action queue, eliminating the need for a schedule, and that's it. The only cross pointers you get are actors targeting other actors. The first thing I do in the destructor is pass the 2 lists a single time, and set the pointers that refer to the dying object to null before the object goes out of scope - it takes literally 1 line of code in a do/while loop, and eliminates the need for a manager class as well as null pointer references.
Yes, I do have to peel off the objects when I save and then write them out manually, but that all occurs in one easily maintainable spot (and what other way would you do it anyways?). Each object has a unique id that sets the pointers back up when I load the game. Its an easy way to do it that I think the OP can grok as he is learning a language. (swizzling as you say)
Maybe I'm unrealistically biased, but I just like super encapsulation with a one-way pointer system; I definitely have produced spaghetti before, going overboard with pointers, but its something everyone does as they are learning. (I should add I usually avoid 2-way pointer structures for the very reasons you described; eg, doubly linked lists)
My entire argument is based on simplicity of coding; of course doing it the way you described produces in a more robust system that results in more stable memory use and eliminates null pointers/run time reference errors, but I don't think this is a beginner task. (After all, GML is supposed to be newbie friendly with its drag and drop IDE.) I don't even know if it's possible to do it this way in GML, but I could be mistaken.
Either way it goes, I think the real take away from all this conversation is that the
OP quit reading this thread a long time ago (either scared off, or went elsewhere when told to do it themselves.)