By Sai Kiran R, Chandan D Y
Recently, we developed a unity application for HoloLens which uses Vuforia services to upload images to the cloud and recognize them when scanned the product again then, we thought of making the application to work on cross-platforms like Android and iOS. First, we cross compiled the application to Android using Unity Editor by Setting the Target Platform as Android which worked fine with no issues. When we targeted to iOS platform, the app started crashing on click of next button which uploads the image to the cloud.
On debugging the application compiled for iOS using a break point, we observed a weird error saying that the “pointer being freed was not allocated”. However, we did not observe any kind of issues in the Android build.
malloc :*** error for object 0 x xyz : pointer being freed was not allocated *** set a breakpoint in malloc_error_break to debug [Iphone][Unity]
So what could be the problem…?
Unity treats every UI screen as a scene and it uses Scene Management to navigate between scenes. During cross platform compilations, Unity converts the code to the target platform’s native code. This was a hint for us to look into Android and iOS Architecture and Memory Management as the error being thrown is related to Memory Management. We know that Android uses its own Garbage Collector whereas iOS uses Automatic Reference Counting (ARC) that provides automatic memory management of Objective-C objects so we started investigating the problem in that direction and started looking for the pointer which was causing the issue. While debugging using iOS Xcode, we found that the pointer referencing the webcam-texture is the root cause. Webcam-texture pointer holds memory to the Raw Image Buffer of the camera and this pointer is used to upload the captured image to Vuforia cloud on Next button click ( What happens actually on click of Next Button is, to go to Next screen; Unity unloads the current scene to load the Next one) and Vuforia cleans all the pointers of the current scene before it moves to the next and ARC of iOS also tries to clear the Pointer before navigating to the next Screen and, as the pointer was already cleared and ARC not able to find the pointer, the application would crash on click of the next button.
This is because in iOS the pointer referencing the webcam-texture is stored in a ARC but, iOS was trying to clear the pointer referencing webcam-texture which was already cleared by Vuforia code.
Currently, iOS memory management uses malloc to allocate memory for every object, so the memory returned is indeed contiguous. According to Apple your app risks being shut down for memory usage when you use more than 20mb of RAM. If you try to allocate more than available contiguous memory the malloc call will return NULL (and probably something else will fail when trying to access a null pointer if not properly checked).
To overcome this issue we stopped webcam-texture explicitly to release the pointer before navigating to another scene, when explicitly stopped; ARC also removes the pointer from its Stack as webcam-texture.Stop() releases the pointer and ARC will not try to dealloc the pointer while moving to next screen.
There are 2 issues in total that were fixed:
* Memory corruption or crash if you use GetPixels() and call Stop().
* The Memory leak in GetPixels() (continuous capture section), leading to run out of memory.
We achieved this using the code below on the Next button click (Code Underlined)
Note that if you use _webcamtexture.stop(); without a coroutine (coroutine handles multi-tasks and run them in Parallel), the app crashes again. So instead use _webcamtexture.stop(); within a coroutine to stop webcam-texture.
So friends, now you know what to do when you are compiling your Unity Code to iOS.