Hidden Game.exe Crash Debugger - Graphical Object Global Reference ACE

Discussion in 'RGSS3 Scripts (RMVX Ace)' started by Mithran, Aug 26, 2013.

  1. Mithran

    Mithran Global Moderators Global Mod

    Messages:
    405
    Likes Received:
    207
    First Language:
    English
    Graphical Object Global Reference VX ACE
    (game.exe crash debugger)​
    by Mithran​
    NOTICE: This is the VX ACE version of the script. For the VX Version go HERE
    Introduction
    Well, it looks like VX Ace isn't completely immune from this problem after all. The root cause appears to be the same, but there is at least one other factor in the ACE crash that is yet to be discovered. Fortunately, fixing the cause will stop the crash.

    The root cause of this error is not properly disposing of Sprites/Windows/Planes associated with a disposed viewport. There is no RGSS Player error message for this practice, but it can lead to Game.exe crashes. Script creators, please do your part and ensure you properly dispose your graphics objects, before they become an issue. This script can help you locate sprites you may have missed.

    You may be suffering from this error if you install a custom script then start getting intermittent crashes:
    "Game.exe has encountered a problem and needs to close"
    "RGSS3 Player has stopped working"


    This is one of the most frustrating errors to deal with in RPG Maker VX as it seems to come and go at random, only affecting certain people or setups, and the actual cause of the error is hidden to you.

    If your project is getting even occasional Game.exe crashes after installing a custom script, this may be worth a read. Please note that this script can only log and debug game.exe crashes having to do with a script problem. If you are crashing without custom scripts installed, the source of your crash is something else and this script will not help.

    This script addresses one specific issue that can cause an unhandled exception leading to an eventual Game.exe crash. The error is much rarer and harder to expose in VX Ace than VX, but I finally have confirmation that it is happening. This error is caused by a simple scripting mistake that would otherwise throw no error message, so it is at least worth a look.

    AUTHOR'S NOTE: The following description primarily describes the VX (RGSS2)
    version of the crash. The VX ACE crash shares some circumstances with the VX
    crash. This script and instructions were written to address the VX issue then
    updated to work in VX ACE. This script itself may or may not stop crashes in ACE
    as it did with VX, but it can be used to log undisposed sprites and stop the
    error from happening in the first place.

    The cause of a given Game.exe crash could be any number of things - anything that
    doesn't create throw an error in Ruby, but causes an unhandled exception in one
    of the 'hidden' classes.

    After extensive testing, I was finally able to recreate the circumstances leading
    up to one such exception that, if left unhandled, could lead to Game.exe crash.

    1. A "GO" - Graphical Object (Sprite, Window, Plane, or Tilemap) is created
    2. The Graphical Object is assigned a Viewport
    3. The Viewport is disposed, but the sprite is not
    ?? - VX ACE Version. There is a yet unknown factor that also needs to happen.
    4. The Graphical Object is claimed by GC (garbage disposal)*

    * - Newly Discovered: attempting to dispose a sprite that has a disposed viewport
    will occasionally also crash. (v 1.1)
    Note that this particular crash only seems to occur if screen draws have taken
    place (any of the Graphics methods) between the time the viewport is disposed
    and the sprite disposal is attempted.

    Due to the way GC is implemented, you are unlikely to see an immediate effect
    when the situation comes up. It could be several scene changes down the line
    before the crash finally happens. To make matters worse, following the exact
    same course of action will yield completely different results, making it seem
    as though the crashes are random. In addition, there is yet another circumstance
    which I have still been unable to pinpoint, but I suspect has something to do
    with the order in which assets associated with the Graphical Object are claimed
    by the GC, or the amount of screen rewdraws that have taken place,
    that allows the GO to be cliamed without causing an exception and
    thus making it even harder to find.

    In essence: you could be suffering from an unstable game and not even know it.

    So that is where this little script comes in. This does the following:

    1. Creates a global variable backreference to every Graphical Object created.
    This prevents them from being marked by the GC so long as the reference exists,
    circumventing the final condition to cause this version of the crash.

    2. Removes reference to the Graphical Object once it has been disposed.
    This reallows the object to be marked by GC for disposal (once all other
    references are removed). Since the GO is disposed, condition 3 is no longer met
    and the object is deemed 'safe'.

    3. Report on potential issues to the user.
    This allows the user (given limited scripting knowledge) to identify potential
    errors and fix them outright.

    4. Prevents further Game.exe crashes caused by this specific issue.
    Includes a 'lazy' fix that cleans up offending Graphical Objects when the scene
    changes.*

    * v 1.1 'Lazy' fix has been superceeded to prevent crashes caused by disposal of
    these errant sprites. Lazy fix only works if debug criticial disposal has
    been disabled. Lazy mode is NOT recommended for ACE users.

    Version History:

    v 1.2 VX ACE
    Discovered possibility of crash in RGSS3. Thanks to Galv for bringing the
    problem to my attention and supplying a script to use as a test case.
    Updated logging features to specificially work with VX ACE. RGSS Console must
    be enabled to recieve live updates.
    Added GOBJ_ABRIDGED_LOG option.
    Altered some terms in the log. Specifically changed the term 'non-critical object'
    to 'Memory Leak' so the term 'Critical Object' can be easily searched in the log.
    Time in log now refers to creation time of the object, rather than time log was written.

    v 1.1
    Discovered a new condition for a Game.exe crash. Updated script to trap and log
    this error also.

    v 1.01-1.05
    Minor bugfixes, improved logging, added consideration for Plane objects viewport method error

    v 1.0
    Initial Release
    Features
    - Identifies and reports a prevalent, and generally very easy to fix, cause of Game.exe crashes.
    - Creates a global reference to every graphical object created until it is disposed to prevent the error from causing this specific Game.exe crash while it is running
     
    Script
    http://pastebin.com/DvuinNFU

    How to Use
    Install on its own script page in the materials section of the script editor above main and below default scripts. If using a script that creates sprites at startup (eg. Jets Mouse System), this script must come after it on the list.

    FAQ
    Q: Game.exe crashes for me constantly and this didn't help!
    A: As explained, this only prevents Game.exe crashes caused by the specific set of circumstances outlined. Crashes caused by memory faults or other errors may still remain, but if there is an in-game reason for it (read: crashes happen after x set of actions are taken with a fair degree of consistency, or across several computers) feel free to leave a post here.

    Q: I'm using a cracked version and..
    A: Support will not be given for non-official versions. Using a cracked version is also against the forum rules, among other things, and will get you banned.

    Q: I found another way to force a Game.exe crash in a seemingly stable game.
    A: I'd love to hear about it. Drop a post with the details.

    Credit and Thanks
    - Mithran (author)
    - Galv, for bringing this to my attention and being able to point me to an ACE script that can cause this crash

    Author's Notes
    For distribution, please link to this thread. May be used in any project, so long as the full header, credit, and instructions remains intact. As with all my debugging scripts, credit for the project as a whole is NOT required

    Bug Reporting
    If you encounter an error, please provide the complete error code as well as a short description on how to reproduce.

    Need Help?
    If you are logging errors in GOBJ.txt but unsure how to fix them, you may post here asking for help. In order for me to even look at your project, I will need at bare minimum a complete copy of your scripts.rvdata2 file (preferably the entire project) and the GOBJ.txt log file. I can't guarantee I will be able to look at every project immediately.

    If you are not logging any errors and continue to crash with my script installed (or crash without custom scripts), please explore other possibilities of the crash before posting in this thread.
     
    Last edited by a moderator: Jan 16, 2014
    #1
    Reapergurl, Dymdez, GGSlayer and 11 others like this.
  2. gecebd

    gecebd Villager Member

    Messages:
    16
    Likes Received:
    0
    First Language:
    French

    Attached Files:

    • gobj.txt
      File size:
      310 bytes
      Views:
      29
    #2
  3. Chaos17

    Chaos17 Dreamer Veteran

    Messages:
    1,240
    Likes Received:
    411
    Location:
    France
    First Language:
    French
    #3
  4. Mithran

    Mithran Global Moderators Global Mod

    Messages:
    405
    Likes Received:
    207
    First Language:
    English
    @Chaos17 -


    Line 546

    Code:
        if @fog_sprite
    Should be:
    Code:
        if @fog_sprites
    Please update to the ACE version of my debug script posted in this thread, you are using the version for VX that does not log completely for ACE.
     
    #4
    Chaos17 likes this.
  5. Chaos17

    Chaos17 Dreamer Veteran

    Messages:
    1,240
    Likes Received:
    411
    Location:
    France
    First Language:
    French
    Edit :
     

    Holy god!

    You were right, I can't beleive it a simple typo could do that!! O_O

    Thank you very much!!

    I will update my post with the other errors : memory leaks.

    I want to clean up all the codes if possibe to avoid bugs.

    Edit 2 :

    Please, help me again if possible.

    I really think cleaning code to avoid bugs is important.

    Here the log error for memory leak : http://pastebin.com/aCdMCgw6

    I compile all the errors that are about the scene_battle.

    My scripts.rvdata2 : https://www.dropbox.com/s/2s42yz51o0mqu0f/Scripts.rvdata2

    I updated the script like you told me.

    If you need anything else, please tell me.
     
    Last edited by a moderator: Dec 30, 2013
    #5
  6. Mithran

    Mithran Global Moderators Global Mod

    Messages:
    405
    Likes Received:
    207
    First Language:
    English
    Normally windows are stored as instance variables within the scene and are automatically disposed when the scene changes, but in this case, they are only stored in instance variables within other windows that do not specifically dispose them. In both cases, these sub windows were hidden by their respective handling window when they were done, but never disposed. These were not considered critical in this case because they weren't associated with a viewport, so no extra risk of a Game.exe crash.

    Install this patch somewhere toward the bottom of your scripts, it needs to be lower than both the scripts mentioned in the second log:

    Code:
    class Window_Message  alias dispose_mith_leak_fix_face_window dispose  def dispose    @face_window.dispose if @face_window    dispose_mith_leak_fix_face_window  endendclass Window_ChoiceList  alias dispose_mith_leak_fix_help_window dispose  def dispose    @help_window.dispose if @help_window    dispose_mith_leak_fix_help_window  endend
    Note that I have not tested either fix since I can't playtest with just a scripts file, but it should work. My concern would be about the second fix, since help_window can be shared between more than one window and is normally handled by the scene and not one specific window only, but this does not appear to be the case in this instance, at least with your current set of scripts.
     
    #6
    Archeia likes this.
  7. Chaos17

    Chaos17 Dreamer Veteran

    Messages:
    1,240
    Likes Received:
    411
    Location:
    France
    First Language:
    French
    Hi again,

    Thank you very much for this patch.

    I tested it while doing a playthrough in my game and I don't see any more in the GOBJ.text any error concerning the : Window_Help. :rock-right:

    Also, I appreciate that you're explaining to me the reasons of the errors because even if I can't fix them I like to understand what's happening.

    Unfortunaly there're still a lot of none critical errors that your script picked up, there're all about Sprite but not in the same Scene : Scene_Battle, Scene_Menu, Scene_Map.

    Here's a quick compilation of the log : http://pastebin.com/iK5rG4fz

    Full error log : https://www.dropbox.com/s/qfr51c5nsyhsiue/gobj.txt

    My : scripts.rvdata2

    I'm sorry for all of this but I think too that a clean code is important for avoiding bugs and man, I know something about bugs...
     
    Last edited by a moderator: Dec 30, 2013
    #7
  8. Mithran

    Mithran Global Moderators Global Mod

    Messages:
    405
    Likes Received:
    207
    First Language:
    English
    A couple of these were pretty much the same error as the windows, just some invisible sprites being left in memory when the scene switches.

    Here is the patch:

    EDIT: Yeah, that one didnt work. See belowSame disclaimer as before, let me know if it doesn't work and I might have typoed something.For the second fix there, I included a dispose for both @arrow_up and @arrow_down. Neither were ever disposed that I could see, but only @arrow_up was flagged by my script for some reason. If that happens to break something, let me know.

    The logged error for the Transition script is more that likely a false positive. My script does most of its logging on a scene switch, and if there are any sprites left in memory at that point, they are flagged as memory leaks, as about 99% of sprites are handled by the scene or in objects within the scene and should be cleaned up by this point. However, certain legitimate scripts might keep a sprite in memory for other reasons (eg., a mouse script with a cursor sprite that persists between scenes). Best I can tell by my finger trace, the transition sprite is stored in its own module and is cleanly disposed when a new one is created, so there should not be a memory leak here.

    Fortunately, I did include a way to exempt certain sprites from being logged. The following code should exempt these transition sprites from being logged:

    class Sprite_Transition alias initialize_mith_fix_exempttransition initialize def initialize(*args) initialize_mith_fix_exempttransition(*args) @transition.gobj_exempt endendAll in all, you shouldn't be too worried about the non-critical errors. The amount of memory consumed by an invisible sprite that is not being updated is so tiny that you would need thousands of them to make a noticeable impact on your game. I actually renamed this from 'non-critical' to 'memory leak' just so the search terms would be easier to independently search. The logged leaks might not actually even really 'leak' when they are Garbage Collected (which does happen to orphaned sprites, whether or not they have had dispose called) My script actually prevents sprites from being orphaned by way of a simple global array for all non-disposed sprites, thus actually consuming slightly more memory as orphaned sprites will never be garbage collected. The memory used by sprites/windows/etc. is actually very small because they are simply containers for the actual graphical device interface objects - bitmaps. So if you have a ton of 'memory leak' during actual playtime, you probably wouldn't notice at all, without my script installed anyway.Keeping an excessive amount of sprites in memory can be detrimental to performance (Graphics module still considers them), however, in normal play you will never reach a level where you would notice without both having this script installed and having tons of undisposed sprites or rapid fire scene switches. Having a few hundred extra live invisible non updated sprites in memory won't hurt you - but a few thousand will probably slow you down a bit. Without my script installed, these orphaned sprites would be harmlessly garbage collected with a potential very small memory leak, upping the number to tens, possibly hundreds of thousands before you would likely notice anything (far beyond even a rigorous stress test).

    Actually, that does bring to light that this script doesn't really do anything for these type of errors. The original intent was to give scripters a tool to be able to detect a "silent killer" before the Game.exe crashes start flying in, then it was expanded to keep the process alive for debugging, then again so that users like yourself can simply plug and play it to save your project if you couldn't find anyone to fix it, with the non-critical/'memory leak' detection tacked on more to remind scripters of good practice when dealing with sprites (since these could have easily been 'critical', if they had been associated with a viewport). I guess I could re-purpose or extend the 'lazy' option to include these types of errors, too.
     
    Last edited by a moderator: Jan 2, 2014
    #8
    Draek97 and Chaos17 like this.
  9. Chaos17

    Chaos17 Dreamer Veteran

    Messages:
    1,240
    Likes Received:
    411
    Location:
    France
    First Language:
    French
    Hi,

    Sorry for the late reply and thank again for your help and explanation.

    I justed tested your patches and I got this error :

    [​IMG]
     
    #9
  10. Mithran

    Mithran Global Moderators Global Mod

    Messages:
    405
    Likes Received:
    207
    First Language:
    English
    Game_Message should have been Window_Message:

    Code:
    EDIT: Derped again.  See below for ultra real actual patch
     
    Last edited by a moderator: Jan 2, 2014
    #10
  11. Chaos17

    Chaos17 Dreamer Veteran

    Messages:
    1,240
    Likes Received:
    411
    Location:
    France
    First Language:
    French
    The new patch made Yami pop up message script crash XD

    [​IMG]

    Yami script: http://pastebin.com/fnaJ3wif

    Log error: http://pastebin.com/C2zwzN0Q

    I see that that the pop message script do come back a lot in your error log....

    I would've agreed with you if I didn't see my FPS rise up after your patches.

    Before yours' patches my FPS was between 20 and 40 or 50 FPS.

    Now I'm between 30 and 60 B)

    With your help, I'm able to understand how important is to have a clean code and I'm really happy with the result I get thanks to you.

    Happy new year :D
     
    #11
  12. Mithran

    Mithran Global Moderators Global Mod

    Messages:
    405
    Likes Received:
    207
    First Language:
    English
    And a Happy New Year to you, too.

    :facepalm:

    Yeah, I hooked the creation method instead of the dispose method there for some reason. Fixed below. I still have no idea why @arrow_down was not detected, though, since it is created in the same method as @arrow_up and also never disposed.

    class Window_Message alias dispose_bubble_sprite_mith_fix_memleakbubblesprite dispose def dispose @bubble_sprite.dispose if @bubble_sprite dispose_bubble_sprite_mith_fix_memleakbubblesprite endendclass Scene_Menu alias terminate_mith_fix_memleakarrowsprites terminate def terminate @arrow_down.dispose if @arrow_down @arrow_up.dispose if @arrow_up terminate_mith_fix_memleakarrowsprites endendI'm glad you got an FPS gain out of the fixes, but any noticeable drop would have probably been caused by this script in the first place. Keeping the global list can drag you if you have a lot of sprites floating around in memory, but during my tests I would only have an FPS drop at numbers > 500 (though by 5000 the game is basically unplayable for me). Without the global list, there is no noticeable drop in FPS at the 5000 mark, and mem usage is only approx 100kb more (than if they were disposed), which does indicate a possible memory leak, but it is very small. By comparison, if you had never created these 5000 sprites, you'd be using about 500kb less memory (which would lend that ALL sprites are leaky, but it could just be the way they are managed by garbage collection). When you happen to create and orphan all 5k sprites at once though, you will notice a dip while they are garbage collected. This is sprites with no associated bitmaps, but orphaned bitmaps are also be garbage collected in the same way. You'll crash if you have over 10,000 bitmaps (the default per process GDI object limit for Windows XP, 7, and Vista) that have not been disposed or garbage collected, but if that happens something has already gone very, very wrong.Logging is also fairly expensive for the process, but this normally takes place during the black in between scenes so it should not impact (long term) FPS at all. The FPS in the process window is an estimate anyway, you can tell when minimize the window that the FPS will tank (because the Game pauses when it hits the next Graphics call, the time between graphics updates is longer and the FPS is lower) and take a couple seconds to level back off.

    As an aside, I did not bother optimizing logging at all so there is a new IO write on every log. You should clean out, move, or delete the log file every once in a while.

    All that being said, I do understand wanting to clean up code and avoid any potential errors; especially considering how innocuous the mistake that actually does lead to Game.exe crashes seems. The best way to prevent more is to remind script creators just how important proper sprite disposal can be. Though I don't mind stepping in time to time to slap some patches together, I will be privately contacting each of the scripters from the mentioned scripts (already have for some), so they might be performing their own fixes directly in the script and hopefully you won't need to use my hastily thrown together and untested minipatches forever. Do let me know if there are more, though, I can usually identify the issue pretty quickly through a hand trace.
     
    #12
    Chaos17 likes this.
  13. Chaos17

    Chaos17 Dreamer Veteran

    Messages:
    1,240
    Likes Received:
    411
    Location:
    France
    First Language:
    French
    Is it just an example or did I had really 5000 orphans'sprites ? o_o

    I'm sorry to ask you this because my english isn't really good.

    If yes, no wonder that my FPS droped at some point *faint*

    Yup, I noticed that but I understood that it was because I was switching between fullscren and window mode.

    My drop of FPS happened mainly during exploration and the most noticeable place were during battle.

    Can you tell me how to do and what file exactly ?

    Sorry, I'm not used with different names.

    The voice of user/noob doesn't have the same impact as the voice of a coder like you.

    Probably because users like me would't be able to explain with technical terms what is happening and we could only "feel" that's something isn't normal.

    Though, I don't know why but after this patch :

    class Sprite_Transition  alias initialize_mith_fix_exempttransition initialize  def initialize(*args)    initialize_mith_fix_exempttransition(*args)    @transition.gobj_exempt  endendVictors'fog script bug because after a battle the fog disappear XD

    But it seems I don't have any more reports from your log *happy*

    Victor script : http://pastebin.com/tZF54pLb

    Thank you again for your help and that you didn't told me "that's your fault if your game lag" instead you properly explained everything.
     
    #13
  14. Mithran

    Mithran Global Moderators Global Mod

    Messages:
    405
    Likes Received:
    207
    First Language:
    English
    Nah, 5000 was the upper limit of my test numbers when I tested my script in a clean project. There is a hard limit of 10000 at a time (window effects cease to function with that many sprites in memory, and at 10000 bitmaps you hit a GDI overflow and crash the whole thing). And that 10000 limit is only if you have them all in memory at once, if you allow some time for some to be garbage collected (garbage collection = reclamation of memory from objects no longer in use; which is what happens when there is no way for the program to find the object anymore, all references have been removed but it still is taking up memory, what I meant by 'orphaned'), you can leak even more and not really notice. The point was you can leak an excessive amount of sprites and not even notice any ill effects (but if you keep them around on purpose, like my script does, you will notice the lag sooner). You are (were) leaking one sprite per error per scene transition - only a handful per process. My numbers were just for comparison.

    Gobj.txt. You can safely move, delete or rename the log file, since it writes everything in 'append' mode and just keeps getting bigger even if it was the same error over and over (it logs one time per leak, even if it is the same one per process). If you have been using the same logfile through all playtests, it could be getting pretty big. I once had someone complain that my script was lagging them and it turned out they had logged almost 10mb of the same unresolved errors 0.o When the file reopens for every write, it also has to find the end to append so it can be a bit laggy as the file gets bigger. When you don't log anything, you stop accessing the file so it doesn't really matter at this point, but there is really no point in keeping it around.
    Yep, thats why I notified them myself. Awareness still seems low on the whole issue, which is a shame because the 'random' Game.exe crashes killed many a VX project back in the day when nobody knew what was causing them.

    Doubt it was that fix but the one right before it (where I had you just add an 's' on the end of fog_sprite), which specifically fixes the issue where battle fog is not disposed. Is it supposed to be persistent and now its not? This same method that disposes the sprite also appears to remove all current fogs, meaning it might be intentional to drop all fogs when you leave battle. I did notify Victor about the typo and he said that it might be why battle fogs were acting strange so there could be another issue at work.
     
    #14
    Chaos17 likes this.
  15. Chaos17

    Chaos17 Dreamer Veteran

    Messages:
    1,240
    Likes Received:
    411
    Location:
    France
    First Language:
    French
    Yeah, I will do more testing and comeback to you.

    That's pretty sad to know that :(

    Specially when those error might happen just because of typo.

    As a noob I'm pretty shocked that such a crash is caused by something so small.

    I wonder how did you took this discovery.

     Ok, I was a bit worried for moment, lol XD

    Though, I understnd your point of view and it's kinda scary to kow that windows might crash in unique situation like the test you did!

    Ok, i usually delete it after a playthrough or patch of yours ;)
     
    Last edited by a moderator: Jan 2, 2014
    #15
  16. Mithran

    Mithran Global Moderators Global Mod

    Messages:
    405
    Likes Received:
    207
    First Language:
    English
    Nah, Windows wouldn't crash, just the Game. The upper limit for GDI objects in Windows is 65535. Unless you modified your registry or had a lot going on in the background, you wouldn't crash Windows.


    I finally cracked this bug when a commercial project I had done some commission work on started crashing. I'll spare the details, but it was many hours of blind guessing, research, and more guessing before I finally figured out what was causing the crashes, from there I made this script and it was easy to work around. Turned out there were four different errors from different scripts (none turned out to be mine) contributing to the crash. If it were less bugged, I probably wouldn't have gotten it to crash as consistently and I might never have found the error, every project I had been given before that did not crash consistently enough for me to nail down the problem, so it couldn't even be traced to being a script issue. By that time, ACE English release was 2 weeks away, so many people were already moving away from VX. So it felt really good to unravel the mystery of one of the longest standing bugs with VX, but it sucked that it was too late for the people that had already abandoned their projects in the past years. Some the bugged scripts are no longer being updated and are still be circulated with the error in them, but at this point most VX users just use my VX script to plug the hole rather than trying to get the actual error fixed.
     
    #16
    Chaos17 likes this.
  17. BigEd781

    BigEd781 undefined method 'stupid_title' found for nil:NilC Veteran

    Messages:
    940
    Likes Received:
    301
    Location:
    Austin, TX
    First Language:
    Dothraki
    Primarily Uses:
    N/A
    So, you have done a lot more work in this area than I have (and I haven't searched through this thread), but have you considered something like this?

    class Bitmap @@instances = {} attr_reader :disposed alias :gc_fin_init :initialize def initialize(*args) id = generate_uuid @@instances[id] = self ObjectSpace.define_finalizer(self, self.class.finalize(id)) @disposed = false gc_fin_init(*args) end alias :gc_fin_dispose :dispose def dispose disposed = true end # this must be a class method to avoid maintaining a reference to self (i.e., no GC ever!) def self.finalize(id) proc { obj = @@instances[id] obj.dispose unless obj.disposed } endendI'm just trying to mimic an RAII style of deallocation in Ruby, a fail safe that triggers when an object is GC'd. I see two potential problems here:1. I don't know all of the subtleties which may surround finalizers in Ruby.

    2. I don't know the internals of the Ruby GC used in RM.

    1 is easy enough to figure out, 2 is trickier. If, for example, Ruby uses a memory threshold before running the GC, you may still encounter problems as the finalizer will never run if you stay under the threshold. Worse, the GC may simply decide not to call the finalizer at all as this behavior is not guaranteed. This stuff is implementation specific, so testing would need to be done.

    Anyway, just a thought. I haven't run any tests of my own.
     
    Last edited by a moderator: Jan 2, 2014
    #17
  18. Girostrike

    Girostrike Sponge Veteran

    Messages:
    66
    Likes Received:
    0
    Location:
    California, US
    First Language:
    English
    Would there be any reason why the console wouldn't show any info or for the gobj.txt not to appear anywhere?
    I'm trying to use this to identify the cause of an error I'm getting.
     
     
    #18
  19. Mithran

    Mithran Global Moderators Global Mod

    Messages:
    405
    Likes Received:
    207
    First Language:
    English
    EDIT:


    @girostrike


    If you aren't getting a log or any console messages then there are not any undisposed sprites in memory when the scene switches, so this script probably won't cover whatever is wrong.


    @BigEd781


    Yeah, that was among the first things that I tried (in the RMVX/Ruby 1.8.3 version anyway, but from what I have read this still holds true). The problem is twofold there,


    1) Any object with ANY accessible reference will not be garbage collected, this includes within class variables. If even a closure with the scope that references the object in question remains, it will never be GC'd. The only references that don't count are the ones in ObjectSpace. It will stop GC completely if you GC.disable, but the RGSS player won't run for long when you do (mem usage rapidly on maps, probably due to the way Tilemap works, and even though stuff like moving a cursor in a window) so I struck this as an option even for debugging. You can fiddle with the memory allocation a bit, but I never did because it didn't seem helpful here without being able to control exactly which objects were not to be touched and which needed to be disposed right now.


    2) Finalizers are called after the object is destroyed. They are not like destructors where you can ensure something happens to the object in question right before it is destroyed. In addition, __id2ref cannot be called with the object_id passed into the finalizer - there is no way to retrieve the object and do anything with it at this point.


    Even if it did work like that, given what I know now, I likely would have had to have scrapped this implementation anyway. The chances of crash are greater after the first scene transition and less after (probably because it has already been GC'd without incident) that, so unless I could guarantee a GC before a scene switch I would still be risking the Game.exe crash. Once GC hits the specific set of circumstances described in my first post, it seems it either crashes, or it doesn't. Even these set of circumstances I can only force the crash about 5% of the time in ACE. In VX I could force it 100% crash with a single errant sprite, while mixing several other sets of variables (but always undisposed sprite + disposed viewport + GC) which is how I was finally sure of what was leading to the crash.


    The best idea I could come up was what I did for the script, to selectively circumvent GC in situations where it would be dangerous (by keeping the objects global array, thus ensuring a permanent reference and no GC) and log the errors so they can be dealt with. It was never really intended to turn into a band-aid for keeping games alive for actual gameplay, but I guess as long as it works. I did put a GOBJ_LAZY switch in there to automatically dispose of any sprites that may trigger a crash left when the scene switches (since 99% of the implementation of sprites/windows/etc are local to one specific scene), but I superceeded it with another option that will prevent the disposal at any point after it can cause the crash. I'm thinking of repurposing the 'lazy' switch to only dispose non critical sprites left over when the scene switches, for everyone that really doesn't like debugging, since the non-criticals can cause performance issues if too many of them are saved from the GC and I've never had a crash associated with them. Actually, maybe I'll just remove them from the global reference after they are logged and let GC do its thing like it would have anyway.


    The original version of this script was actually just single line that just prevented Viewport from ever being disposed. That alone prevents 100% of the crashes at the cost of less than a kb per error (most of which is later harmlessly GC'd anyway, since the objects still get orphaned). It might leak a bit but it is still nothing compared to what is already being leaked by other things anyway. I have no way to even prove 100% that it is leaking except the small different in memory usage between creating thousands of sprites, disposing them, and letting GC eat them, and just creating thousands of sprites and letting GC eat them. (I mentioned in an earlier thread, a consistent approx 100kb difference for 5000 sprites). I guess that would be the ultimate band-aid fix, but I really didn't want to encourage doing that.


    Bitmaps are actually a different area here. This script doesn't really touch them, or consider them. They can also be GC'd even if not disposed and are (possibly) slightly leaky when done so. I just know that they are the actual GDI objects (not sprites/plants/windows, which are just containers) based on research and tests. You can't have 10k bitmaps because you'll GDI overflow. You can't have 10k sprites because as long as they are in memory, they still need to be considered by Graphics, whether they are visible or not, even if they were never updated or assigned a bitmap. You can go higher than 10k without killing the program, but you can't really do much at 0FPS.
     
    Last edited by a moderator: Jan 2, 2014
    #19
  20. Shaz

    Shaz Veteran Veteran

    Messages:
    35,429
    Likes Received:
    9,924
    Location:
    Australia
    First Language:
    English
    Primarily Uses:
    RMMV
    @mithran, girostrike's issue has to do with battle testing. Here's the discussion topic.


    This script doesn't show anything at all when the game crashes in battle test?
     
    #20

Share This Page