Page 1 of 2 12 LastLast
Results 1 to 10 of 30

Thread: Yet another segfault (a.k.a. Darkhog is a total noob)

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    It's in Allegro.pas distribution under (allegro.pas)\addons\OGG_Vorbis\lib

    //edit: Also to access debug screen press right ctrl+left shift+d on main menu.

  2. #2
    PGD Staff / News Reporter phibermon's Avatar
    Join Date
    Sep 2009
    Location
    England
    Posts
    524
    You've got two 'isColliding' member functions as part of TGameObject but you've not overloaded them. This should give you an error in objfpc mode as far as I'm aware.

    You're range checking 'CurrentAnim' but you're not range checking 'GO.CurrentAnim' which you also use. Not saying that's the issue but you should be meticulous about such things.

    I'm getting the build environment setup so I can compile and debug this for you, will have you an answer asap

    EDIT : You're also calling 'inherited create' from your TAnimatedSprite constructor but the parent class doesn't have it's constructor marked as virtual.

    User137 is correct, you don't have 'Create' defined in the TAnimatedSprite interface but you do have it in the implementation section. As a result you're not calling that 'Create' in your Gameobject creation, instead it'll be calling whatever 'Create()' it next finds, probably TObject.

    I don't mean this is an offensive manner, but I've learned some things today, I'd of said this would never compile! but there lies the executable

    Edit : BAADF00D isn't just an amusing coincidence you know, look it up

    Edit : You had your compiler optimization on the highest setting, this will prevent you from debugging properly.
    Last edited by phibermon; 27-07-2013 at 08:14 PM.
    When the moon hits your eye like a big pizza pie - that's an extinction level impact event.

  3. #3
    PGD Staff / News Reporter phibermon's Avatar
    Join Date
    Sep 2009
    Location
    England
    Posts
    524
    Ok found it and sort of fixed it.

    Oh yeah sorry, I should tell you shouldn't I?

    procedure TSprite.UpdateMask;

    if ActualMaskBitmap<>nil then al_destroy_bitmap(ActualMaskBitmap); //preventing memory leak

    Replace with :

    if ActualMaskBitmap<>nil then
    begin
    al_destroy_bitmap(ActualMaskBitmap);
    ActualMaskBitmap := nil;
    end;



    -----


    the actual error happens on the al_bitmap_mask_color calls in collide in masked_collision.pas :

    function collide( Sprite1: TSprite; Sprite2: TSprite):boolean;

    mask1 := al_bitmap_mask_color(sprite1.ActualMaskBitmap);
    mask2 := al_bitmap_mask_color(sprite2.ActualMaskBitmap);


    I noted on the crash that ActualMaskBitmap was an invalid reference (just junk data at the time of the call)

    However this points to a much more serious problem as it would appear that you've got more than one thread executing code across your program at the same time, the error is actually appears to be happening because al_destroy_bitmap(ActualMaskBitmap); is called in UpdateMask and then before it can be created again, the collide function tries to use it with al_bitmap_mask_color.

    My fix isn't a real fix and it can still crash inbetween these two calls :

    al_destroy_bitmap(ActualMaskBitmap);
    ActualMaskBitmap := nil;

    before the pointer is set to nil. al_bitmap_mask_color must contain code that just breaks out if it gets a null pointer.

    I'd reccomend that you stop the multi-thredded execution (find out how and where it's doing that, allegro is probably firing off events or something in a seperate thread, something like that)

    and stop re-creating these masks all the time, you should store all the masks for all the frames as well.

    if you *never* called al_destroy_bitmap() on these masks, IE don't call updatemasks, find some other way of doing it then you might find it never crashes. I should expect my 'fix' would eventually crash, it'd just be pure chance if the al_bitmap_mask_color function gets called before that reference is set to nil.

    But unless you really know what you're doing, you're only going to hit even harder problems with multi-threadded execution as your code base grows in size.


    EDIT: I can confirm that sooner or later (20 seconds or so of continual sprite intersection in my case but could literally be at any moment) it'll break again. I'd eat my hat if I'm wrong about the threadding. I shall post pictures too


    EDIT EDIT : you're using Allegro timers. They are seperate threads (at least on the windows platform, not in DOS). there's your source. You should use mutexes etc to synchronize access to shared resources such as these bitmap masks or otherwise stop using the timers.
    Last edited by phibermon; 27-07-2013 at 08:55 PM.
    When the moon hits your eye like a big pizza pie - that's an extinction level impact event.

  4. #4
    Quote Originally Posted by phibermon View Post
    User137 is correct, you don't have 'Create' defined in the TAnimatedSprite interface but you do have it in the implementation section. As a result you're not calling that 'Create' in your Gameobject creation, instead it'll be calling whatever 'Create()' it next finds, probably TObject.
    Is he?

    Quote Originally Posted by User137 View Post
    Had another quick look on the github. Are you calling right constructor for TAnimatedSprite?
    Code:
    constructor TGameObject.Create(mode: TObjectMode);
    begin
      if mode=omAnim then Animations:=TAnimatedSpriteList.create;
    the .Create is TObject.Create, it seems. The .Create without parameters is not written to either TAnimatedSprite or TSprite.
    Let's repeat code part, shall we?
    Code:
    constructor TGameObject.Create(mode: TObjectMode);
    begin
      if mode=omAnim then Animations:=TAnimatedSpriteList.create;
    Yup, just as I thought. I'm not creating TAnimatedSprite, but TAnimatedSpriteList. Slight difference, you know? And guess what, it does have parameter-less constructor.

    Also where did you get that BAADF00D from? It doesn't appear anywhere during compilation, debugging or in my posts...

    And thanks for optimization tip, I've just turned it off.

    //edit: Sorry that I might sound a bit rude, but I have today my birthday. No one gave me wishes except some automatic from websites and I didn't even get a cake. And yes, I can also exclude "surprise birthday party" as day is almost ending (23:22 or 11:22PM).
    Last edited by Darkhog; 27-07-2013 at 09:23 PM.

  5. #5
    No, i wasn't correct on my guess last time. Can you perhaps zip the source+media files, and attach to forum post? Would be easier to test with compiler...

  6. #6
    You can clone my git repo... It's pretty current one.

  7. #7
    Yeah found the download link Either you commented the bugs away, or fixed it, but i don't see problems in menu.
    PS. phibermon edited his post with fixes.

  8. #8
    Quote Originally Posted by User137 View Post
    Yeah found the download link Either you commented the bugs away, or fixed it, but i don't see problems in menu.
    PS. phibermon edited his post with fixes.
    No, you need to access debug screen. It's right ctrl+left shift+d in main menu. Then, after you touch "other" mario with submarine, game'll crash.

  9. #9
    PGD Staff / News Reporter phibermon's Avatar
    Join Date
    Sep 2009
    Location
    England
    Posts
    524
    Happy birthday

    It's your update() method in the main unit that's running in a separate thread via an Allegro timer, if you call that in your main thread loop instead then that'll fix your problem.

    You are correct about the create defintion, so my apologies However if me and 137 made exactly the same mistake then it might suggest your code could benefit from some formatting.

    I'm only teasing I'm glad we found the issue, it's a great project and please keep the updates on progress coming!
    When the moon hits your eye like a big pizza pie - that's an extinction level impact event.

  10. #10
    Just to echo something that was said earlier...

    Whenever you use the condition:

    If SomePointerReference <> Nil Then

    it is much better (more portable, readable, etc) if you use this instead:

    If Assigned(SomePointerReference) Then

    It is an inline function/macro, so it shouldn't be less efficient.

Page 1 of 2 12 LastLast

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •