Quick Links: Download Gideros Studio | Gideros Documentation | Gideros Development Center | Gideros community chat | DONATE
get a crash by movieclip — Gideros Forum

get a crash by movieclip

XmanXman Member
edited January 2017 in General questions
(lldb) bt
popBalloon iOS was compiled with optimization - stepping may behave oddly; variables may not be available.
* thread #1: tid = 0x4e67fa, 0x000000010314fa10, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=2, address=0x10314fa10)
frame #0: 0x000000010314fa10
* frame #1: 0x000000010024023c popBalloon iOS`Sprite::eventListenersChanged() [inlined] Sprite::getStage(this=) const + 16 at sprite.cpp:737 [opt]
frame #2: 0x000000010024022c popBalloon iOS`Sprite::eventListenersChanged(this=) + 28 at sprite.cpp:1078 [opt]
frame #3: 0x0000000100234464 popBalloon iOS`void EventDispatcher::removeEventListener(this=, type=, obj=, func=)(EnterFrameEvent*)) + 184 at eventdispatcher.h:138 [opt]
frame #4: 0x0000000100231a58 popBalloon iOS`MovieClip::oneFrame() [inlined] void EventDispatcher::removeEventListener(this=0x0000000145ef55d0, type=)(EnterFrameEvent*)) + 160 at eventdispatcher.h:146 [opt]
frame #5: 0x0000000100231a38 popBalloon iOS`MovieClip::oneFrame() [inlined] MovieClip::stop(this=0x0000000145ef55d0) + 4 at movieclip2.cpp:1238 [opt]
frame #6: 0x0000000100231a34 popBalloon iOS`MovieClip::oneFrame(this=0x0000000145ef55d0) + 124 at movieclip2.cpp:1074 [opt]
frame #7: 0x00000001002321a0 popBalloon iOS`MovieClip::nextFrame(this=0x0000000145ef55d0, (null)=) + 44 at movieclip2.cpp:1114 [opt]
frame #8: 0x00000001002209dc popBalloon iOS`EventDispatcher::dispatchEvent(this=, event=) + 136 at eventdispatcher.h:203 [opt]
frame #9: 0x0000000100247b40 popBalloon iOS`Stage::enterFrame(this=, deltaFrameCount=, lastFrameRenderTime=) + 552 at stage.cpp:97 [opt]
frame #10: 0x000000010028ee18 popBalloon iOS`enterFrame(L=) + 212 at luaapplication.cpp:1024 [opt]
frame #11: 0x00000001002d92bc popBalloon iOS`luaD_precall(L=, func=0x00000001468f2420, nresults=) + 540 at ldo.c:319 [opt]
frame #12: 0x00000001002d5290 popBalloon iOS`luaD_call(L=0x0000000145d103b0, func=0x00000001468f2420, nResults=0) + 116 at ldo.c:376 [opt]
frame #13: 0x00000001002d8d48 popBalloon iOS`luaD_rawrunprotected(L=0x0000000145d103b0, f=(popBalloon iOS`f_call at lapi.c:816), ud=0x000000016fddd630) + 76 at ldo.c:116 [opt]
frame #14: 0x00000001002d53bc popBalloon iOS`luaD_pcall(L=0x0000000145d103b0, func=, u=, old_top=32, ef=) + 56 at ldo.c:468 [opt]
frame #15: 0x00000001002d5350 popBalloon iOS`lua_pcall(L=0x0000000145d103b0, nargs=0, nresults=0, errfunc=) + 112 at lapi.c:837 [opt]
frame #16: 0x00000001002ceb00 popBalloon iOS`::lua_pcall_traceback(L=0x0000000145d103b0, nargs=0, nresults=0, unused=) + 184 at luautil.cpp:172 [opt]
frame #17: 0x000000010028e31c popBalloon iOS`LuaApplication::enterFrame(this=0x00000001740f3500, status=0x000000016fddd770) + 164 at luaapplication.cpp:1085 [opt]
frame #18: 0x00000001002a7dd8 popBalloon iOS`ApplicationManager::drawFrame(this=0x0000000170147850) + 312 at giderosapi.mm:991 [opt]
frame #19: 0x000000010002b718 popBalloon iOS`-[ViewController drawFrame](self=0x0000000145e08580, _cmd="drawFrame") + 24 at ViewController.m:152
frame #20: 0x0000000100a97ae4 GPUToolsCore`-[DYDisplayLinkInterposer forwardDisplayLinkCallback:] + 176
frame #21: 0x0000000191f0af24 QuartzCore`CA::Display::DisplayLinkItem::dispatch(unsigned long long) + 44
frame #22: 0x0000000191f0add0 QuartzCore`CA::Display::DisplayLink::dispatch_items(unsigned long long, unsigned long long, unsigned long long) + 444
frame #23: 0x000000018ef22094 IOKit`IODispatchCalloutFromCFMessage + 372
frame #24: 0x000000018ec4ae50 CoreFoundation`__CFMachPortPerform + 180
frame #25: 0x000000018ec63218 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 56
frame #26: 0x000000018ec629cc CoreFoundation`__CFRunLoopDoSource1 + 436
frame #27: 0x000000018ec604b0 CoreFoundation`__CFRunLoopRun + 1840
frame #28: 0x000000018eb8e2b8 CoreFoundation`CFRunLoopRunSpecific + 444
frame #29: 0x0000000190642198 GraphicsServices`GSEventRunModal + 180
frame #30: 0x0000000194bd57fc UIKit`-[UIApplication _run] + 684
frame #31: 0x0000000194bd0534 UIKit`UIApplicationMain + 208
frame #32: 0x0000000100026580 popBalloon iOS`main(argc=1, argv=0x000000016fddf938) + 108 at main.m:12
frame #33: 0x000000018db715b8 libdyld.dylib`start + 4
(lldb)
«1

Comments

  • XmanXman Member
    edited January 2017

    It seems something changed in movieclip.
    In my code, I cache the movieclip for reuse, it never crashed before
  • hgy29hgy29 Maintainer
    Yep, something changed in MovieClip recently: MovieClip could previously be garbage collected while playing. This was corrected in 2016.12, however fixing it led to another bug because some variable was not correctly intiialized. It was fixed in 2016.12.1... Which version are you using ?
  • the latest code on GitHub I built myself.
  • XmanXman Member
    edited January 2017
    If movie clip is used as a normal sprite, it should not be garbage collected while playing.
    I guess the way that maybe garbage collected is the movieclip is used to run an action for a sprite, and not added to the stage.
  • As the creator of the engine told us years ago, movieclip should be used just as a normal sprite, do not use it run actions, use gtween instead.
  • @hgy29
    when the movieclip is still playing, remove it from the parent will cause a crash.
  • hgy29hgy29 Maintainer
    Hi @Xman, I tried several times and couldn't make it crash (on windows).

    I used the following code:
    sprite=Bitmap.new(Texture.new("fleche.png",true))
     
    local mc = MovieClip.new{
    	{1, 100, sprite, {x = {0, 200, "linear"}}}
    }
     
    mc:setGotoAction(100,1)
    stage:addChild(mc)
     
    Timer.delayedCall(2000,function () mc:removeFromParent() end)
  • remove the setGotoAction and try it. It crashed when the movie clip completed
  • it's a little complicated to figure out what code exactly cause this, let me try to make a simple demo to reproduce it.
  • XmanXman Member
    edited January 2017
    @hgy29
    do
     
    local frames = {}
    for i = 1, 100 do
     frames[i] = {i, i, Bitmap.new(Texture.new('art/logo.png'))}
    end
     
    local mc = MovieClip.new(frames)
     
    local sprite = Sprite.new()
     
    sprite:addChild(mc)
     
    stage:addChild(sprite)
     
    --this is like a user operation.
    Timer.delayedCall(10, function() sprite:removeFromParent() sprite = nil collectgarbage() end)
     
    --we may do some works when the mc is completed if no user operation
    --mc:addEventListener(Event.COMPLETE, function(event) mc:removeFromParent()  end)
    end
  • XmanXman Member
    edited January 2017
    I don't know what use case need this modification for MovieClip.
    But add a reference count to a MovieClip when playing to prevent it from garbage collected may not a good solution. It may cause unexpected problems in some situations such as the parent has been released by a user operation, then the movieclip should not still be playing.
  • hgy29hgy29 Maintainer
    From what I saw in gideros docs and various examples, movieclip sprite need not to be actually on stage, which means that it is often created as a local object and possibily garbage collected at any time, which is not good either. Movieclip are often used as fire and forget effects...

    I added this because another user had random crashes related to movieclip being garbage collected while playing. Since both use case are possible, it is hard to tell which way is better.
  • I think if the movie clip is not used to added to stage, the user self should know clearly when the reference is needed and when to discard it in Lua side.
  • XmanXman Member
    edited January 2017
    at first I used a lot to not to add the movie clip to stage, and keep the reference
    myself. but Atilim Cetin told me that it's not what MovieClip intended to be, it should be used as a sprite and add to stage.
    GTween is exactly for that situations.
  • hgy29hgy29 Maintainer
    IMHO, whatever Atilim may have told, Gideros should still never crash while trying to be as smart as possible. I admit I didn't think about the looping case, which could end up eating memory if not manually stopped by the user. Maybe Gideros could detect the looping case and stop looping if the MC is not on stage ? That way we would have the best of both options, don't you think ?

    Anyway this doesn't explain why it crashes in your situation, because adding a reference should not make it crash.

    Likes: totebo

    +1 -1 (+1 / -0 )Share on Facebook
  • XmanXman Member
    edited January 2017
    You maybe misunderstood me.
    Now my crash is adding the MC to stage, and the parent of the MC is collected before the MC completed. it would crash when the MC completed.

    I mean if MC is not added to stage, we can keep a reference to it in Lua code to prevent it from collected just like any other object.

    I think the user should be responsible for which object needed to keep, either add it to the stage or reference it.

    Of course, I can fixed the crash by stopping the MC when it is removed from the stage.
    But it's not a good solution in my opinion.

    Why not just revert the MovieClip to the original, do not make it too complicated.
  • hgy29hgy29 Maintainer
    I don't understand why the fact the the parent of the MC is collected before the MC is completed would necessarily make the MC crash on complete, unless MovieClip has some other bug that prevent it for being properly detached from its parent when the latter is destroyed.

    I know that the coder could keep a reference to it, but if we can relieve the user from doing it, why not ?
  • hgy29hgy29 Maintainer
    edited January 2017
    Reading the code, it looks like the bug might be that Sprite.cpp's destructor just unref() its children, while it should also clear their parent link to NULL!

    EDIT: Just did that and the example you gave above no longer crashes!
  • The above code can produce the crash 100%. But it will not crash on release 2016.10.
    delete sprite = nil will not crash
  • hgy29hgy29 Maintainer
    Whatever, I can revert if everyone think it is best, but since most exemples I've seen don't bother keeping a reference to the Movieclip, I still think it was a good idea at first!
  • Then, the user have to take care of whether all the MovieClips needed to be stopped or still let it playing when change scene.
  • Whatever, I can revert if everyone think it is best, but since most exemples I've seen don't bother keeping a reference to the Movieclip, I still think it was a good idea at first!
    All these examples will not stop crashing until the in coming release.
    But all the code runs well will get problems in the future release.
    It's not easy to make a seamless solution.
  • if another MC is used to just move a sprite or some similar just as tween did, it my be not required to inherent from Sprite.
  • XmanXman Member
    edited January 2017
    Or consider to add a parameter to distinguish these two situations MovieClip.new(timeline,holdWhilePlaying)
  • hgy29hgy29 Maintainer
    Yes, a new parameter might be the best solution: true=hold while playing, false=don't hold, nil/unset=hold while playing until the first goto action (loop) ?
  • XmanXman Member
    edited January 2017
    nil=don't hold. Just to keep behavior the same as old releases.
    Other values choose whatever you prefer :)
    May be an enum like ONE_LOOP, UNTIL_COMPLETE
    But it seems ridiculous to hold a loop MC until the first gotoaction.Maybe just leave this situation to the users themselves to hold a reference to decide when to stop it. They must keep a reference to stop it when it's not needed
  • XmanXman Member
    edited January 2017
    Or to make a little simple,just a bool parameter, true to hold,false or nil to not hold.
    For a looping MC,it's impossible to not keep a reference in code.Without a reference it can't be stopped at all.
  • XmanXman Member
    edited January 2017
    However,I still can not imagine why create a MC to move a sprite,and just leave the MC to the game engine to collect it when completed. If the sprite is removed ,it will not be collected until the MC complete.and the coder can do nothing to release the sprite without a reference to the MC
  • hgy29hgy29 Maintainer
    Accepted Answer
    Well for short lived animations it is just less hassle I suppose, I am kind of lazy when programming :) But I got the point and I will revert my change so that it works exactly as it used to
    +1 -1 (+2 / -0 )Share on Facebook
  • I'm so happy that finally I successfully persuaded you to give up this change.

    Likes: hgy29

    +1 -1 (+1 / -0 )Share on Facebook
Sign In or Register to comment.