GLEngine allocateWCMemory Leak Debugging

Hi all!

I’m attempting to track down the root cause of a memory leak on our IOS game, but have hit the limits of my knowledge. Here’s what I’m seeing (openfl 2.2.7, lime 2.1.2) -

   0 libsystem_kernel.dylib mach_vm_map
   1 GLEngine allocateWCMemory
   2 GLEngine glBufferData_Exec
   3 CineMagic nme::OGLContext::RenderData(nme::HardwareData const&, nme::ColorTransform const*, float const (&) [4][4])
   4 CineMagic nme::Graphics::Render(nme::RenderTarget const&, nme::RenderState const&)
   5 CineMagic nme::DisplayObject::Render(nme::RenderTarget const&, nme::RenderState const&)
   6 CineMagic nme::DisplayObjectContainer::Render(nme::RenderTarget const&, nme::RenderState const&)
   7 CineMagic nme::DisplayObjectContainer::Render(nme::RenderTarget const&, nme::RenderState const&)
   8 CineMagic nme::DisplayObjectContainer::Render(nme::RenderTarget const&, nme::RenderState const&)
   9 CineMagic nme::DisplayObjectContainer::Render(nme::RenderTarget const&, nme::RenderState const&)
  10 CineMagic nme::DisplayObjectContainer::Render(nme::RenderTarget const&, nme::RenderState const&)
  11 CineMagic nme::DisplayObjectContainer::Render(nme::RenderTarget const&, nme::RenderState const&)
  12 CineMagic nme::DisplayObjectContainer::Render(nme::RenderTarget const&, nme::RenderState const&)
  13 CineMagic nme::DisplayObjectContainer::Render(nme::RenderTarget const&, nme::RenderState const&)
  14 CineMagic nme::Stage::RenderStage()
  15 CineMagic nme_render_stage(_value*)
  16 CineMagic ExternalPrimitive::__run(Dynamic const&) /usr/lib/haxe/lib/hxcpp/3,1,68/src/hx/Lib.cpp:122
  17 CineMagic Dynamic::operator()(Dynamic const&) /usr/lib/haxe/lib/hxcpp/3,1,68/include/Dynamic.h:176
  18 CineMagic openfl::_v2::display::Stage_obj::__render(bool) ./src/openfl/_v2/display/Stage.cpp:1707
  19 CineMagic openfl::_v2::display::Stage_obj::__checkRender() ./src/openfl/_v2/display/Stage.cpp:610
  20 CineMagic openfl::_v2::display::Stage_obj::__pollTimers() ./src/openfl/_v2/display/Stage.cpp:1672
  21 CineMagic openfl::_v2::display::Stage_obj::__doProcessStageEvent(Dynamic) ./src/openfl/_v2/display/Stage.cpp:688
  22 CineMagic openfl::_v2::display::Stage_obj::__processStageEvent(Dynamic) ./src/openfl/_v2/display/Stage.cpp:891
  23 CineMagic openfl::_v2::display::__Stage_obj__processStageEvent(hx::Object*, Dynamic const&) ./src/openfl/_v2/display/Stage.cpp:897
  24 CineMagic hx::CMemberFunction1::__run(Dynamic const&) /usr/lib/haxe/lib/hxcpp/3,1,68/include/hx/DynamicImpl.h:138
  25 CineMagic val_call1 /usr/lib/haxe/lib/hxcpp/3,1,68/src/hx/CFFI.cpp:602
  26 CineMagic external_handler(nme::Event&, void*)
  27 CineMagic nme::Stage::HandleEvent(nme::Event&)
  28 CineMagic IOSStage::OnPoll()
  29 CineMagic -[NMEAppDelegate mainLoop]
  30 Foundation __NSThreadPerformPerform
  31 CoreFoundation __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__
  32 CoreFoundation __CFRunLoopDoSources0
  33 CoreFoundation __CFRunLoopRun
  34 CoreFoundation CFRunLoopRunSpecific
  35 CineMagic -[NMEAppDelegate mainLoop]
  36 Foundation __NSThreadPerformPerform
  37 CoreFoundation __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__
  38 CoreFoundation __CFRunLoopDoSources0
  39 CoreFoundation __CFRunLoopRun
  40 CoreFoundation CFRunLoopRunSpecific
  41 CineMagic -[NMEAppDelegate mainLoop]
  42 Foundation __NSThreadPerformPerform
  43 CoreFoundation __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__
  44 CoreFoundation __CFRunLoopDoSources0
  45 CoreFoundation __CFRunLoopRun
  46 CoreFoundation CFRunLoopRunSpecific
  47 GraphicsServices GSEventRunModal
  48 UIKit UIApplicationMain
  49 CineMagic nme::CreateMainFrame(void (*)(nme::Frame*), int, int, unsigned int, char const*, nme::Surface*)
  50 CineMagic nme_create_main_frame(_value**, int)
  51 CineMagic ExternalPrimitive::__Run(Array<Dynamic> const&) /usr/lib/haxe/lib/hxcpp/3,1,68/src/hx/Lib.cpp:159
  52 CineMagic Dynamic::operator()(Dynamic const&, Dynamic const&, Dynamic const&, Dynamic const&, Dynamic const&, Dynamic const&) /usr/lib/haxe/lib/hxcpp/3,1,68/include/hx/DynamicImpl.h:542
  53 CineMagic openfl::_v2::Lib_obj::create(Dynamic, int, int, hx::Null<double>, hx::Null<int>, hx::Null<int>, String, hx::ObjectPtr<openfl::_v2::display::BitmapData_obj>, hx::ObjectPtr<Class_obj>) ./src/openfl/_v2/Lib.cpp:321
  54 CineMagic ApplicationMain_obj::main() ./src/ApplicationMain.cpp:177
  55 CineMagic __hxcpp_lib_main ./src/__lib__.cpp:12
  56 CineMagic hxRunLibrary /usr/lib/haxe/lib/hxcpp/3,1,68/src/hx/RunLibs.cpp:29
  57 CineMagic main /Users/bbooth/work/hs_client/HollywoodShuffle/export/ios/CineMagic/Classes/Main.mm:121
  58 libdyld.dylib start

I see lots of these, around 10MB worth over 20min, just enough to put the game over the edge. So I guess my ask is:

  • How should I start figuring out the root cause of the leak?
  • Barring that, is there a way to forcibly clear GLEngine allocated memory (crazy, I know :smile: )

Thanks!

Have you tried using HxScout yet? I’ve found that to be VERY helpful when looking at garbage collection activity, objects in memory, and other things to profile

I’ll give it a go, last time I tried it crashed immediately, but that was on the android platform.

Don’t forget, if you run on a mobile device, you’ll need to configure the IP address of your host system (running HxScout) in order for it to connect. I think the download page may describe how to do this with OpenFL (<config:telemetry host="" /> I think?)

yeah, definately, though I think I’m running a version of openfl that doesn’t have that config flag supported yet. I’ll just read the install docs. :smile:

hmm, looks like I need to upgrade hxcpp to use telemetry:

Error: ./src/hxtelemetry/HxTelemetry.cpp:243:14: error: no member named '__hxcpp_hxt_start_telemetry' in the global namespace
                int _g = ::__hxcpp_hxt_start_telemetry(this->_config->profiler,this->_config->allocations);             HX_STACK_VAR(_g,"_g");
                         ~~^
./src/hxtelemetry/HxTelemetry.cpp:373:5: error: no member named '__hxcpp_hxt_ignore_allocs' in the global namespace
                ::__hxcpp_hxt_ignore_allocs((int)1);
                ~~^
./src/hxtelemetry/HxTelemetry.cpp:441:5: error: no member named '__hxcpp_hxt_ignore_allocs' in the global namespace
                ::__hxcpp_hxt_ignore_allocs((int)-1);
                ~~^
./src/hxtelemetry/HxTelemetry.cpp:459:5: error: no member named '__hxcpp_hxt_ignore_allocs' in the global namespace
                ::__hxcpp_hxt_ignore_allocs((int)1);
                ~~^
./src/hxtelemetry/HxTelemetry.cpp:517:5: error: no member named '__hxcpp_hxt_ignore_allocs' in the global namespace
                ::__hxcpp_hxt_ignore_allocs((int)-1);
                ~~^
./src/hxtelemetry/HxTelemetry.cpp:816:7: error: no member named '__hxcpp_hxt_ignore_allocs' in the global namespace
                                ::__hxcpp_hxt_ignore_allocs((int)1);
                                ~~^
./src/hxtelemetry/HxTelemetry.cpp:853:7: error: no member named '__hxcpp_hxt_ignore_allocs' in the global namespace
                                ::__hxcpp_hxt_ignore_allocs((int)-1);
                                ~~^
./src/hxtelemetry/HxTelemetry.cpp:866:5: error: no member named '__hxcpp_hxt_ignore_allocs' in the global namespace
                ::__hxcpp_hxt_ignore_allocs((int)1);
                ~~^
./src/hxtelemetry/HxTelemetry.cpp:891:5: error: no member named '__hxcpp_hxt_ignore_allocs' in the global namespace
                ::__hxcpp_hxt_ignore_allocs((  ((set_disabled)) ? int((int)1) : int((int)-1) ));
                ~~^
9 errors generated.

What’s the max version of hxccp I can use safely with openfl 2.2.7 and lime 2.1.2?

Alright, I upgraded to hxcpp 3.2.171 per the hxtelemetry documentation and now get this EXC_BAD_ACCESS, which I also find hard to debug. :smile:

 * thread #1: tid = 0x6e19d, 0x00000001003ca1fc CineMagic`hx::ArrayBase::getPodSize(this=0x0000000000000000) const + 12 at Array.h:230, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x18)
  * frame #0: 0x00000001003ca1fc CineMagic`hx::ArrayBase::getPodSize(this=0x0000000000000000) const + 12 at Array.h:230
    frame #1: 0x00000001003c9aea CineMagic`Array<int> Dynamic::StaticCast<Array<int> >(this=0x00007fff5fbfa700) const + 42 at Operators.h:280
    frame #2: 0x0000000100978ef6 CineMagic`com::jamwix::hs::cards::CardInventory_obj::loadCollectionRewards(this=0x00000001102944f8) + 1382 at CardInventory.cpp:247
    frame #3: 0x0000000100978336 CineMagic`com::jamwix::hs::cards::CardInventory_obj::__construct(this=0x00000001102944f8) + 1094 at CardInventory.cpp:140
    frame #4: 0x0000000100978890 CineMagic`com::jamwix::hs::cards::CardInventory_obj::__new() + 96 at CardInventory.cpp:186
    frame #5: 0x0000000100a67f47 CineMagic`com::jamwix::hs::Game_obj::__construct(this=0x0000000110276be8) + 4375 at Game.cpp:524
    frame #6: 0x0000000100a69740 CineMagic`com::jamwix::hs::Game_obj::__new() + 96 at Game.cpp:667
    frame #7: 0x0000000100b511b1 CineMagic`HollywoodShuffle_obj::init(this=0x00000001102764cc, e=<unavailable>) + 881 at HollywoodShuffle.cpp:149
    frame #8: 0x0000000100b515f5 CineMagic`__HollywoodShuffle_objinit(inObj=0x00000001102764cc, inArg0=0x00007fff5fbfbc00) + 85 at HollywoodShuffle.cpp:187
    frame #9: 0x0000000100c27b77 CineMagic`hx::CMemberFunction1::__run(this=0x0000000110276684, inArg0=0x00007fff5fbfbc00) + 71 at DynamicImpl.h:138
    frame #10: 0x000000010000305d CineMagic`Dynamic::operator(this=0x00000001102766f4, inArg0=0x00007fff5fbfbc00)(Dynamic const&) + 93 at Dynamic.h:197
    frame #11: 0x0000000100b95995 CineMagic`openfl::_v2::events::EventDispatcher_obj::dispatchEvent(this=0x00000001102764cc, event=<unavailable>) + 1813 at EventDispatcher.cpp:205
    frame #12: 0x0000000100b64dea CineMagic`openfl::_v2::display::DisplayObject_obj::__dispatchEvent(this=0x00000001102764cc, event=<unavailable>) + 570 at DisplayObject.cpp:340
    frame #13: 0x0000000100b62f73 CineMagic`openfl::_v2::display::DisplayObject_obj::dispatchEvent(this=0x00000001102764cc, event=<unavailable>) + 179 at DisplayObject.cpp:123
    frame #14: 0x0000000100b6769b CineMagic`openfl::_v2::display::DisplayObject_obj::__onAdded(this=0x00000001102764cc, object=<unavailable>, isOnStage=true) + 923 at DisplayObject.cpp:598
    frame #15: 0x0000000100b5b562 CineMagic`openfl::_v2::display::DisplayObjectContainer_obj::__onAdded(this=0x00000001102764cc, object=<unavailable>, isOnStage=true) + 178 at DisplayObjectContainer.cpp:881
    frame #16: 0x0000000100b68372 CineMagic`openfl::_v2::display::DisplayObject_obj::__setParent(this=0x00000001102764cc, parent=<unavailable>) + 978 at DisplayObject.cpp:695
    frame #17: 0x0000000100b56164 CineMagic`openfl::_v2::display::DisplayObjectContainer_obj::addChild(this=0x00000001030ba878, child=<unavailable>) + 692 at DisplayObjectContainer.cpp:96
    frame #18: 0x0000000100b51e23 CineMagic`HollywoodShuffle_obj::start(e=<unavailable>) + 1091 at HollywoodShuffle.cpp:248
    frame #19: 0x0000000100b51ee0 CineMagic`__HollywoodShuffle_objstart(inArg0=0x00007fff5fbfc8e0) + 48 at HollywoodShuffle.cpp:254
    frame #20: 0x0000000100c277f5 CineMagic`hx::CStaticFunction1::__run(this=0x000000010e156e94, inArg0=0x00007fff5fbfc8e0) + 37 at DynamicImpl.h:170
    frame #21: 0x000000010000305d CineMagic`Dynamic::operator(this=0x000000010e156efc, inArg0=0x00007fff5fbfc8e0)(Dynamic const&) + 93 at Dynamic.h:197
    frame #22: 0x0000000100b95995 CineMagic`openfl::_v2::events::EventDispatcher_obj::dispatchEvent(this=0x000000010e155c04, event=<unavailable>) + 1813 at EventDispatcher.cpp:205
    frame #23: 0x00000001009f8488 CineMagic`com::jamwix::hs::assets::AssetManager_obj::syncConfig(this=0x000000010e155c04, newVersion=169, url=<unavailable>) + 1144 at AssetManager.cpp:369
    frame #24: 0x00000001009f7cc9 CineMagic`com::jamwix::hs::assets::AssetManager_obj::onVersionsDownloaded(this=0x000000010e155c04, res=<unavailable>) + 8361 at AssetManager.cpp:331
    frame #25: 0x00000001009f7ff5 CineMagic`com::jamwix::hs::assets::__AssetManager_objonVersionsDownloaded(inObj=0x000000010e155c04, inArg0=0x00007fff5fbfda28) + 85 at AssetManager.cpp:339
    frame #26: 0x0000000100c27b77 CineMagic`hx::CMemberFunction1::__run(this=0x000000010e157c84, inArg0=0x00007fff5fbfda28) + 71 at DynamicImpl.h:138
    frame #27: 0x000000010000305d CineMagic`Dynamic::operator(this=0x000000010e157edc, inArg0=0x00007fff5fbfda28)(Dynamic const&) + 93 at Dynamic.h:197
    frame #28: 0x000000010033207b CineMagic`com::jamwix::utils::JWRequest_obj::onComplete(this=0x000000010e157ebc, e=<unavailable>) + 1339 at JWRequest.cpp:300
    frame #29: 0x0000000100332315 CineMagic`com::jamwix::utils::__JWRequest_objonComplete(inObj=0x000000010e157ebc, inArg0=0x00007fff5fbfdd10) + 85 at JWRequest.cpp:307
    frame #30: 0x0000000100c27b77 CineMagic`hx::CMemberFunction1::__run(this=0x000000010e660ed4, inArg0=0x00007fff5fbfdd10) + 71 at DynamicImpl.h:138
    frame #31: 0x000000010000305d CineMagic`Dynamic::operator(this=0x000000010e660f1c, inArg0=0x00007fff5fbfdd10)(Dynamic const&) + 93 at Dynamic.h:197
    frame #32: 0x0000000100b95995 CineMagic`openfl::_v2::events::EventDispatcher_obj::dispatchEvent(this=0x000000010e660d44, event=<unavailable>) + 1813 at EventDispatcher.cpp:205
    frame #33: 0x00000001001a60ac CineMagic`openfl::_v2::net::URLLoader_obj::__dataComplete(this=0x000000010e660d44) + 956 at URLLoader.cpp:409
    frame #34: 0x00000001001a587f CineMagic`openfl::_v2::net::URLLoader_obj::update(this=0x000000010e660d44) + 1871 at URLLoader.cpp:351
    frame #35: 0x00000001001a6748 CineMagic`openfl::_v2::net::URLLoader_obj::__pollData() + 488 at URLLoader.cpp:479
    frame #36: 0x0000000100184f1a CineMagic`openfl::_v2::display::Stage_obj::__pollTimers(this=0x00000001030ba4b8) + 234 at Stage.cpp:1506
    frame #37: 0x000000010017bb00 CineMagic`openfl::_v2::display::Stage_obj::__doProcessStageEvent(this=0x00000001030ba4b8, event=<unavailable>) + 2544 at Stage.cpp:599
    frame #38: 0x000000010017d07f CineMagic`openfl::_v2::display::Stage_obj::__processStageEvent(this=0x00000001030ba4b8, event=<unavailable>) + 207 at Stage.cpp:802
    frame #39: 0x000000010017d169 CineMagic`openfl::_v2::display::__Stage_obj__processStageEvent(inObj=0x00000001030ba4b8, inArg0=0x00007fff5fbff058) + 89 at Stage.cpp:808
    frame #40: 0x0000000100c27b77 CineMagic`hx::CMemberFunction1::__run(this=0x00000001030ba6f8, inArg0=0x00007fff5fbff058) + 71 at DynamicImpl.h:138
    frame #41: 0x0000000100b9f656 CineMagic`val_call1(arg1=0x00000001030ba6f8, arg2=0x000000010be2ca98) + 134 at CFFI.cpp:608
    frame #42: 0x0000000103159f6f lime.ndll`___lldb_unnamed_function1335$$lime.ndll + 543
    frame #43: 0x0000000103142ed8 lime.ndll`___lldb_unnamed_function1030$$lime.ndll + 1304
    frame #44: 0x0000000103105f14 lime.ndll`___lldb_unnamed_function32$$lime.ndll + 356
    frame #45: 0x0000000103105d78 lime.ndll`___lldb_unnamed_function31$$lime.ndll + 2056
    frame #46: 0x0000000103159b78 lime.ndll`___lldb_unnamed_function1326$$lime.ndll + 248
    frame #47: 0x0000000100be5c65 CineMagic`ExternalPrimitive::__Run(this=0x00000001030ba318, inArgs=0x00007fff5fbff4e0) + 581 at Lib.cpp:173
    frame #48: 0x0000000100c20d05 CineMagic`Dynamic::operator(this=0x00007fff5fbff6c0, inArg0=0x00007fff5fbff688, inArg1=0x00007fff5fbff650, inArg2=0x00007fff5fbff648, inArg3=0x00007fff5fbff640, inArg4=0x00007fff5fbff638, inArg5=0x00007fff5fbff630)(Dynamic const&, Dynamic const&, Dynamic const&, Dynamic const&, Dynamic const&, Dynamic const&) + 229 at DynamicImpl.h:542
    frame #49: 0x0000000100b7a7dd CineMagic`openfl::_v2::Lib_obj::create(onLoaded=<unavailable>, width=2048, height=1536, __o_frameRate=<unavailable>, __o_color=<unavailable>, __o_flags=<unavailable>, __o_title=<unavailable>, icon=<unavailable>, stageClass=<unavailable>) + 2061 at Lib.cpp:321
    frame #50: 0x0000000100b99579 CineMagic`ApplicationMain_obj::main() + 649 at ApplicationMain.cpp:162
    frame #51: 0x0000000100b9cb1c CineMagic`main(argc=1, argv=0x00007fff5fbffa00) + 60 at __main__.cpp:12
    frame #52: 0x00000001000017b4 CineMagic`start + 52

The code in question is this if statement, _collectionRewards is not null and rewardType is 0:

132                 if (_collectionRewards[rewardType] == null)
133                 {
134                     _collectionRewards[rewardType] = new Array<Int>();
135                 }

and here’s the CPP:

(lldb) fr s 2
frame #2: 0x0000000100978ef6 CineMagic`com::jamwix::hs::cards::CardInventory_obj::loadCollectionRewards(this=0x00000001102944f8) + 1382 at CardInventory.cpp:247
   244 						HX_STACK_LINE(130)
   245 						number = rewards->__get(i).StaticCast< Array< int > >()->__get((int)1);
   246 						HX_STACK_LINE(132)
-> 247 						if (((this->_collectionRewards->__get(rewardType).StaticCast< Array< int > >() == null()))){
   248 							HX_STACK_LINE(134)
   249 							this->_collectionRewards[rewardType] = Array_obj< int >::__new();
   250 						}

Sorry for the spam. :smile:

Hmm, did you do a -clean build after you upgraded HXCPP?

I believe I did, but that was a day ago and my memory is garbage. :smile: If I get back to this today or tomorrow I’ll verify.