Start a new topic

Memory Leak/Crash on iOS

Memory Leak/Crash on iOS

1 person has this problem


I've been playing with Wikitude via the Phonegap/Cordova plugin for a couple of weeks now and have been extremely impressed overall.

While testing my app, I noticed that if I launch and exit my AR World enough times my application would eventually crash.  I then tried the same experiment with your sample Cordova app and experienced the same thing.  After repeatedly entering and exiting one of the AR worlds on the menu (I don't believe the actual world matters but I was using 7.1 - Simple Video), the application would eventually crash.  Shortly before the app crashes, I the lldb console starts indicating a memory warning each time we enter the view and when it does crash, the lldb console indicates "Process xxx exited with status = 0 (0x00000000) Terminated due to Memory Error.  It takes around 20-25 visits to the AR world to cause the problem but it can be reproduced consistently.

Note that this is only happening on iOS.  Android does not seem to have the same issue.

I'm running on iOS 8.3, and using Cordova 4.3.0.

As I'm pretty much following the same patterns as the sample app for launching and closing my AR world and both applications exhibit the exact same behavior, I'm assuming that the issue resides with the native plugin implementation or the Wikitude SDK itself.  If I'm mistaken, please let me know how the source code for the sample app can be modified to correct this issue and, if not, I'm hoping you can provide an ETA for a fix.

Thanks in advance.

Hi Jake,
I will try to reproduce your problem and get back to you with more details.

Thx for reporting your finding.

Best regards

Andreas

Hi Andreas,

Any luck reproducing the problem?

Thanks,

Jake

Hi Jake,
Over the last few weeks I was working on a new feature and will now continue working on reported issues. We will respond to you as soon as possible.

Best regards

Andreas

Hi I'm having the same problem. Only that it takes about 8 times of entering and exiting field of vision for the app to crash

Hi Axel,
What's the implementation of your enter/exitFOV trigger?

Best regards

Andreas

Hi there, I'm pasting it down here but let me do some explaining first for the code is a little complex because it gets data from Firebase service. The code is part of an app that we developed based on wikitude's multiple targets example and works fine (until the 8th or 14th augmentation, depending how many objects it creates at any given OEFV). The complete code can be clone at https://github.com/axelweisz/seeBeyondDemo. To illustrate further the memory problem, we noticed that if we leave the AR screen (that is go back to the home page) the objects do void from memory and the count until the (unforunately inevitable) crash of the app starts over. Well there goes the code:

 

var World = {

loaded: false,

init: function initFn() {

this.createOverlays();

},

createOverlays: function createOverlaysFn() {

//create firebase object

var fb = new Firebase("https://testejsontr.firebaseio.com");

var db = fb.on("value", function(snapshot){

var db = snapshot.val(); //get the whole database

var baseUrl = db.baseUrl;

var tgtColl = db.targetCollection; //get the target collection

//creates the tracker

var tracker = new AR.ClientTracker(baseUrl+tgtColl, {

onLoaded: function worldLoadedFn() {

var e = document.getElementById('loadingMessage');

e.parentElement.removeChild(e);

$("#scanBar").show();

}

});

//create arrays for targets, augmentations and augmentations options

var tgtsArray = db.targets;

var augmentsObjs = db.augments;

var optionsObjs = db.augmentOpts;

//create the arrays that will store the objects (trackable2Dobjects, drawables and camDrawables) 

World.overlaysImg = ;

World.trackablesImg = ;

World.emptyCamArrayImg = ;

/*** MAIN LOOP ***/

//creates a trackable for each target in the target collection (tgtsArray)

for(var i = 0; i < tgtsArray.length; i++){

//create the trackables

World.trackablesImg = new AR.Trackable2DObject(tracker, tgtsArray.name, {

drawables: {

cam: World.emptyCamArrayImg //start the camDrawables with an empty array

},

onEnterFieldOfVision: (function (ii) {

return function(e) {

$("#scanBar").hide();

//loop to try do clean the memory from the objects before creating the augmentations

for(var k = 0; k < World.emptyCamArrayImg.length; k++){

this.drawables.removeCamDrawable(k);

World.emptyCamArrayImg = null;

World.overlaysImg.destroy();

World.overlaysImg = null;

}

var tgtAugmentsArray = tgtsArray.augments;//get the augmentations for each target

for(var j = 0; j < tgtAugmentsArray.length; j++){

var aumentation = augmentsObjs;

var options = optionsObjs;

var file = baseUrl+aumentation.filePath; 

var type = aumentation;

//creating the drawable according to the type of aumentation (image, video, etc)

if(type=="img"){

var imgRes = new AR.ImageResource(file);

World.overlaysImg = new AR.ImageDrawable(imgRes, options.scale, {

offsetX: options.offsetX,

offsetY: options.offsetY,

zOrder: options.zOrder

}

);

this.drawables.addCamDrawable(World.overlaysImg);//add the drawable to camDrawable

} else if(type == "btn"){

var imgRes = new AR.ImageResource(file);

World.overlaysImg = new AR.ImageDrawable(imgRes, options.scale, {

offsetX: options.offsetX,

offsetY: options.offsetY,

zOrder: options.zOrder,

onClick : function() {

AR.context.openInBrowser(options.link, true);

}

 

}

);

this.drawables.addCamDrawable(World.overlaysImg);//add the drawable to camDrawable

}else if (type == "video"){

World.overlaysImg = new AR.VideoDrawable(file, options.scale, {

offsetX: options.offsetX,

offsetY: options.offsetY,

zOrder: options.zOrder, 

isTransparent: options.isTransparent

 

})

this.drawables.addCamDrawable(World.overlaysImg);//add the drawable to camDrawable

World.overlaysImg.play();

}

}

};

})(i),

onExitFieldOfVision: (function (ii) {

return function(e) {

//trying to delete the objects and free the memory also here

var thisTrckbl = this;

var tgtAugmentsArray = tgtsArray.augments;

for(var j = 0; j < tgtAugmentsArray.length; j++){

thisTrckbl.drawables.removeCamDrawable(j);

World.emptyCamArrayImg = null;

World.overlaysImg.destroy();

World.overlaysImg = null;

}

//counting scans

fb.child("scans/"+tgtsArray.name+"/totalScans").transaction(function(currentValue){

return (currentValue||0) + 1

}, 

function(err, committed, ss) {

if( err ) {

  console.log("erro: " + err);

} else if( committed ) {

          console.log("novo valor: " + ss.val()); 

       }

}

);

fb.child("scans/"+tgtsArray.name + "/scanTimes").push({

scan: Firebase.ServerValue.TIMESTAMP

});

$("#scanBar").show();

};

 

 

})(i)

});

}

});

},

 

worldLoaded: function worldLoadedFn() {

var e = document.getElementById('loadingMessage');

e.parentElement.removeChild(e);

}

};

 

World.init();

Hi Axel,
thx for sharing the snippet. I read it and now have some follow up questions:

Are you sure that all drawables (VideoDrawable & ImageResources/ImageDrawables) are .destroyed() before you recreate them in your vision trigger?

Can you send us the crash report? I would be interested if it is a crash because of a null ptr. or memory preasure.

Best regards

Andreas

 

For what it's worth, I never managed to resolve the issue I raised at the beginning of this thread (which appears to be the same as Axel's).  It would be extremely useful if you could provide a version of the demo app that did not exhibit the same crash problem (I tried extensively to get to one, BTW).  We could then use the techniques in that example to design and fix our own apps.

we are having the same issues. When I keep scanning I get memory warnings and then a crash of the app. Attached a log of messages I get from my iphone 4s

 

HI everybody. I tryed to destroy the object when the target exits the field of vision  and when it enters again, before creating the drawables again:

 

onExitFieldOfVision: (function (ii) {

return function(e) {

//trying to delete the objects and free the memory also here

var thisTrckbl = this;

var tgtAugmentsArray = tgtsArray.augments;

for(var j = 0; j < tgtAugmentsArray.length; j++){

thisTrckbl.drawables.removeCamDrawable(j);/**here I remove the cam drawable from the screen***/

World.emptyCamArrayImg = null;  /***here I try to clean the cam drawable object from the array***/

World.overlaysImg.destroy();  /******Trying to the drawable destroy here **********/

World.overlaysImg = null;  /*** here trying to clean the memory ***/

}

}

 


onEnterFieldOfVision: (function (ii) {

return function(e) {

$("#scanBar").hide();

//loop to try do clean the memory from the objects before creating the augmentations

for(var k = 0; k < World.emptyCamArrayImg.length; k++){

this.drawables.removeCamDrawable(k); /**here I remove the cam drawable from the screen***/

World.emptyCamArrayImg = null; /***here I try to clean the cam drawable object from the array***/

World.overlaysImg.destroy(); /******Trying to the drawable destroy here **********/

World.overlaysImg = null; /*** here trying to clean the memory ***/

}


 

Well if you asked me if the objects were really destroyed, I'm not sure because I'm afraid Idon't know how to debug and see if the objects are still there or not. Actualy I tryed your documentation that explains how to debug with safari and found it confusing an couldn't follow it. If you're saying there'se a method .destroyed(), please tell me how to use it because on what object do I call it on? the drawable? How can I know the drawable object name? 

Ok now for the crash report, I ran the app tethered to my computer using cordova cli "run ios --device --debug" command. I copied only the last lines here because I think are the ones that matter. Note there's no crash message, it gives off the warnings and the quit. I think it is good to say that before the warnings start the app stopped showing the images on screen. It would still recognize the target. I know that because when it does it hides the animated "scan bar" that is supposed to show when it has no target in sight. After some more target recognitions, it starts the warnings and then afer some more it quits 

 

 

2016-01-27 11:51:25.464 seeBeyond 6799.625993ms

2016-01-27 11:51:25.465 seeBeyond 6800.108016ms

2016-01-27 11:51:27.078 seeBeyond Resetting plugins due to page load.

2016-01-27 11:51:28.151 seeBeyond Finished load of: file:///var/mobile/Containers/Bundle/Application/A73215BC-A5FD-4927-9434-17F101770B8E/seeBeyond.app/www/index.html

2016-01-27 11:51:35.748 seeBeyond THREAD WARNING: took '167.119873' ms. Plugin should use a background thread.

2016-01-27 11:51:35.937 seeBeyond THREAD WARNING: took '187.864990' ms. Plugin should use a background thread.

2016-01-27 11:52:37.311 seeBeyond Received memory warning.

2016-01-27 11:52:37.393 seeBeyond Received memory warning.

2016-01-27 11:52:38.562 seeBeyond Received memory warning.

2016-01-27 11:52:38.983 seeBeyond Received memory warning.

2016-01-27 11:52:41.610 seeBeyond Received memory warning.

2016-01-27 11:52:41.658 seeBeyond Received memory warning.

2016-01-27 11:52:41.709 seeBeyond Received memory warning.

Hi I remembered that I think it is worth to say that the process restarts when you leave de AR screen, that is when you go back to the home page and forward to the AR screen again. It is like it resets the count and starts showing the augmentations again. If you do that before it crashes of course 

Update: I was testing again and this time it did gave out a crash message (the last line below):

 

2016-01-27 13:07:00.647 seeBeyond Received memory warning.

2016-01-27 13:07:03.543 seeBeyond Received memory warning.

2016-01-27 13:07:03.618 seeBeyond Received memory warning.

2016-01-27 13:07:09.856 seeBeyond Received memory warning.

Process 2762 exited with status = 0 (0x00000000) Terminated due to memory issue

Hi Axel,
THX for sharing the application log. The last one states that the application was terminated die to memory issues. My Idea was that you send me the crash report, but I can work with this information as well. Crash reports are always generated when the application was forced to quit and it also states which process used to much memory. You can find this file in the Xcode ->Window  -> Devices -> *Your Device* -> View Device Logs. A memory crash report looks slightly different than a e.g. null ptr crash report. It would be great if you could send that file as well, so that we see the process which consumed the memory.

You can also start your application directly with Xcode. To do so, open the platforms/ios/*.xcodeproj file.

Best regards

Andreas
Login or Signup to post a comment