Why is RSSG2 Player crashing? :(

Discussion in 'RGSSx Script Support' started by IdkWhatsRc, Aug 18, 2012.

Thread Status:
Not open for further replies.
  1. IdkWhatsRc

    IdkWhatsRc Famous Runescape Youtuber :D Member

    Messages:
    16
    Likes Received:
    0
    Location:
    Montréal
    First Language:
    French
    I've started using GTBS v.1.5.2 and after a battle, there is a chance to the game simply crashes. I don't really know why exactly and I would really like to solve the problem. I'm sure it's about the GTBS script because everything was working fine when I was using the v.1.4 GTBS.

    Note:

    It says that RSSG2 Player crashed. It's NOT a regular Script error even though I'm sure the source of the problem comes from GTBS script.

    [​IMG]

    DEMO: http://www.mediafire.com/?cdn5wyx2p1ws4na

    Thanks.
     
    #1
  2. TDS

    TDS - T D S - Veteran

    Messages:
    361
    Likes Received:
    129
    First Language:
    English
    The old random crash problem. Sadly, it could be so many things that most people never truly find out which one is causing the problem. Most of the time it's something not being disposed of, like a sprite or bitmap, and once you reload a scene it causes it to crash or also once too many objects are left out without being destroyed.
     
    Last edited by a moderator: Aug 18, 2012
    #2
  3. IdkWhatsRc

    IdkWhatsRc Famous Runescape Youtuber :D Member

    Messages:
    16
    Likes Received:
    0
    Location:
    Montréal
    First Language:
    French
    How to solve it then?
     
    #3
  4. Solistra

    Solistra Veteran Veteran

    Messages:
    593
    Likes Received:
    241
    I hate to sound obvious (truly), but it sounds to me like that's exactly what the problem is... there are just too many problems that it could be without a decent way to backtrack and find the root cause.
     
    #4
  5. IdkWhatsRc

    IdkWhatsRc Famous Runescape Youtuber :D Member

    Messages:
    16
    Likes Received:
    0
    Location:
    Montréal
    First Language:
    French
    Nvm... I'm sad...
     
    Last edited by a moderator: Aug 18, 2012
    #5
  6. Mithran

    Mithran Global Moderators Global Mod

    Messages:
    404
    Likes Received:
    212
    First Language:
    English
    On many occasions, its not "random", the source of the error was just never located for a long, long time. See my post here. After briefly checking this project with my script, it does suffer from the issue described. I don't have time right now to completely backtrace the error, but using just using the debug script is also workaround to the error that causes the crash.
     
    #6
  7. IdkWhatsRc

    IdkWhatsRc Famous Runescape Youtuber :D Member

    Messages:
    16
    Likes Received:
    0
    Location:
    Montréal
    First Language:
    French
    If you somehow manage to solve the problem, I will be forever thankful :D
     
    #7
  8. BigEd781

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

    Messages:
    940
    Likes Received:
    303
    Location:
    Austin, TX
    First Language:
    Dothraki
    Primarily Uses:
    N/A
    This is typically why it occurs, and the reason is that RGSS uses Windows GDI graphics API under the covers. calling dispose() on a bitmap releases native resources (GDI handles typically) that are not and cannot be managed by the Ruby garbage collector (though some type of finalization mechanism for these objects would have helped). These resources are finite and, when GDI (windows) runs out... well, that typically results in an exception (crash) and the error messages that GDI throws are notoriously unhelpful. You can reproduce the same thing with something similar in C# (C# because it's short and sweet).



    Code:
    static void main()
    {
      while(true)
      {
       // these classes implement IDisposable, but
       // we create many of them in quick succession and
       // fail to ever call Dispose().  This results in temporary
       // "leaks" and eventually GDI throws an exception
       // ("typically "Invalid Parameter")
       Font f = new Font();
       Bitmap b = new Bitmap(100, 100);
      }
    }
    
    You'll see a crash pretty quickly.

    ...

    Ok, that's my factoid of the day. Carry on.
     
    Last edited by a moderator: Aug 19, 2012
    #8
  9. Mithran

    Mithran Global Moderators Global Mod

    Messages:
    404
    Likes Received:
    212
    First Language:
    English

    Code:
    class Scene_Battle_TBS
    alias battle_start_vicfix battle_start
    def battle_start(*args)
    battle_start_vicfix(*args)
    @vic.dispose
    end
    end
    
    That should prevent the crash directly. Installing the linked script would also stop the crashes, but in a much more roundabout way. There are multiple other instances of Sprites being kept in memory when the scene switches, which is generally unintentional and may be a (small) memory leak, but you need about a thousand of them before it will become an issue. I don't have time to trace them all and see if they are significant. Make sure you are using the most updated version of the script.

    @BigEd781, TDS

    Actually, I managed to find the source of the unhandled exception a while back. The unchecked creation of bitmaps or Sprites may eventually cause a crash here but this specific error is caused by disposing a Viewport without disposing all Sprites that have been associated with it. Without seeing what is under the hood here and based on my tests, it would appear that the Ruby, either when performing GC on these sprites or when allocating memory in their former space, will encounter an unhandled exception. A single Viewport disposed with a single undisposed Sprite associated is enough to cause the crash at an arbitrary point in the future (usually at the next time a large amount of resources are loaded). Simply leaving undisposed Sprites lying around will not cause a crash until much, much later, and performance becomes an issue long before.

    The point of all this, however, is that many of these crashes where "RGSS2 player encountered a problem and needs to close" can all be traced back to this specific error (in fact, in ALL instances where I was sent a project and examined it, I managed to find and correct the described error). An error which can easily be identified and avoided or fixed. That is what http://forums.rpgmak...obal-reference/ does, the original intent was just a debugger to identify situations which might lead to the game.exe crash but it also prevents them by storing a reference to each created Sprite in a global variable, preventing GC of the sprite until disposed, when the reference is then removed from the global list (the reference is kept in the list if deemed 'unstable' and would lead to the crash, thus it will not be GC'd and the exception will not occur). The slow leak was meant to allow the game to continue while gathering further data, but it can also be played in this state with no noticeable effects unless played for an extremely long period of time.
     
    #9
  10. IdkWhatsRc

    IdkWhatsRc Famous Runescape Youtuber :D Member

    Messages:
    16
    Likes Received:
    0
    Location:
    Montréal
    First Language:
    French
    So I simply put that little script and my game doesn't crash anymore?

    Seems too easy to be true. XD
     
    #10
  11. Mithran

    Mithran Global Moderators Global Mod

    Messages:
    404
    Likes Received:
    212
    First Language:
    English
    @idkwhatsrc

    Place it below the GTBS scripts on its own page. That little snip disposes of the sprite that will eventually cause the error as soon as its done displaying.

    Yes, it seems too good to be true because the hard part of this is tracing the error to its source, which is why I created that other script, it easily picks out which objects were not properly disposed by telling you the script and line they were created on. From there its just a matter of finding when they should have been disposed (BEFORE the associated viewport) and patch it to do so. This can sometimes be complicated, but in this case its simple, the Sprite is not even visible after it fades out completely and is not referenced after that, so I just disposed it there. I didn't see any other 'critical' errors in my cursory sweep (following the instructions you left in the demo, basic combat > victory > open /close menus) so you should stop crashing.

    In the event you keep crashing and there is another error, you can follow the link supplied above and get my debugger script. Simply installing it should stabilize the game and report the errors in a logfile, which can then be used by someone with scripting knowledge to track the error and fix it.
     
    #11
  12. IdkWhatsRc

    IdkWhatsRc Famous Runescape Youtuber :D Member

    Messages:
    16
    Likes Received:
    0
    Location:
    Montréal
    First Language:
    French
    Well, so far so good with that 'patch'. :D

    Thanks a lot
     
    #12
  13. BigEd781

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

    Messages:
    940
    Likes Received:
    303
    Location:
    Austin, TX
    First Language:
    Dothraki
    Primarily Uses:
    N/A
    Now that I didn't realize... and it makes far less sense. I wonder what the hell is going on in their engine? If it's not a leak in GDI it makes me wonder if they did actually implement a finalizer for these objects which hold references to native resources and screwed it up. You would think it would just call dispose()... oh well, who knows (wish I had the RGSS source code...)
     
    Last edited by a moderator: Aug 20, 2012
    #13
  14. TDS

    TDS - T D S - Veteran

    Messages:
    361
    Likes Received:
    129
    First Language:
    English
    @Mithran: That is great to know. I've been poking around the viewport class lately trying to see how it works and if it's somehow capable knowing which objects are part of it and this should help with that research.
     
    #14
  15. BigEd781

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

    Messages:
    940
    Likes Received:
    303
    Location:
    Austin, TX
    First Language:
    Dothraki
    Primarily Uses:
    N/A
    You know, it would be simple to extend viewport to automatically dispose or disposable objects in a finalizer (think RAII in C++).
     
    #15
  16. Mithran

    Mithran Global Moderators Global Mod

    Messages:
    404
    Likes Received:
    212
    First Language:
    English
    What is also important is that this set of circumstances doesn't always lead to a crash, only to the possibility of a crash. And the actual time of the crash seems to be mainly when a large amount of resources are shifted (eg., a scene switch), however, this is just speculation as this is not the case 100% of the time. AND if you don't crash within a few scene switches (and the error is not repeated), usually you won't at all. However, every single instance of a crash had, at some time close before it occurred, an instance of a Viewport being disposed without an associated Sprite (or Window, or Plane) and both being left without reference and at the mercy of the Ruby GC. I verified it with a pre-title loop where I created hundreds of Sprites and Viewports, disposing the viewports and leaving the sprites, until I found the minimum number that would trigger a crash (which was a single undisposed sprite). Granted, in order to trigger the crash reliably, I had to create and dispose a bunch of sprites and expose the error on one of them, which is why I am so inclined to believe it is so linked to memory allocation.

    I should also note that this issue seems to have been fixed in the implementation of RGSS3 (and I've never tested it in RGSS).

    All things being equal and as frustrating as this error was for so many years to so many people, the simplest solution is just to not dispose Viewports and then leave around undisposed associated sprites with no reference. There is almost no practical reason to not dispose a sprite if you are going to dispose the Viewport (doing so renders it invisible), the only one I can think of is if you wanted to pass it another Viewport at a later point. However, the crash doesn't occur as long as there is a live reference to the Sprite, so I can think of *no* reason where you would want or need to do this.

    On the flipside of, I've seen this error surface in several of the most popular battle systems for RPG Maker VX, including a version of Yanfly's Melody (if quick enough, you can exit before a fadeout effect has completed, which is linked directly to a sprite disposal), several versions of Tankentai (dummy actors the scene starts with are never disposed), Vlads SBABS (enemy HP bars are Scene specific, but are linked to a viewport in the Spriteset which is disposed on transferring to another map), and now a version of GTBS (victory condition sprite not being disposed when no longer needed). Because it doesn't have a 100% crash rate (some of these also only reached because of a specific set of circumstances) and because it doesn't throw an RGSSError immediately, I suspect very few even know about the cause.

    The best tool we have here is awareness - if you properly free your resources, you won't run into this problem. Not to disparage any of these other creators, who missed one object disposal in thousands of lines of code, in which no feedback is given to let you know that you have made that mistake. That is why I created that "debugger" script, which makes it very easy to identify which object is not being property disposed by tracking them all from their creation. I was hoping more scripters would pick it up, but with the timing (only a few weeks before the English release of ACE), I expect it is mostly being used as a workaround for "making old scripts work".

    Anyway, enough rambling from me. If anyone wants to do some further testing, I've had good results replicating the crash with this:

    http://pastebin.com/raw.php?i=23LNNhuS

    @TDS

    Viewport has no method by default where you can check all sprites associated with it (at least not one that can be determined with Ruby relection). You could add one accomplish this by modifying the initialize and viewport= method of Sprite (and Plane, Tilemap and Window), and to store back a representation (eg., its ID) of the Sprite in the Viewport. I found it easier to just track everything globally, so I could track the associated sprites after the viewport was already disposed (which is when I was most interested in them in this case). Also note that the documentation is incorrect on a few instances here - Viewport#disposed? is not implemented, and the Plane viewport methods don't work how they are supposed to (see my debug script toward the bottom for my fixes for these). This is, of course, for RGSS2, in RGSS3 the Plane -viewport method issues have been fixed, though there is still no implementation of Viewport#disposed? like the manual says, and no method to check the associated sprites.

    So since the original issue seems solved and we are straying a bit,

    This thread is being closed, due to being solved. If for some reason you would like this thread re-opened, please report this post and leave a message why. Thank you.

    I made an "official" sticky topic for the game.exe crashing issue causes/solutions where discussion on that can continue for anyone that is interested:

    http://forums.rpgmak...needs-to-close/
     
    #16
Thread Status:
Not open for further replies.

Share This Page