I’ve been writing a small app at the moment that manipulates images in REALBasic (now called XOJO) and came across a peculiar crash. Basically, I’m drawing images into a larger image and after loading 100 images and drawing them into other files, it ended up crashing. Nothing could be caught. I soon realised that it was a memory issue (reaching over 4 gigs).
This was in the dump I was experiencing:
0 libsystem_kernel.dylib 0x96074a6a __pthread_kill + 10
1 libsystem_c.dylib 0x90c2aacf pthread_kill + 101
2 libsystem_c.dylib 0x90c614f8 abort + 168
3 libc++abi.dylib 0x92ea880c abort_message + 151
4 libc++abi.dylib 0x92ea6275 default_terminate() + 34
5 libc++abi.dylib 0x92ea62b5 safe_handler_caller(void (*)()) + 13
6 libc++abi.dylib 0x92ea631d std::terminate() + 23
7 libc++abi.dylib 0x92ea7412 __cxa_throw + 110
8 libstdc++.6.dylib 0x995092f6 operator new(unsigned long) + 127
9 libstdc++.6.dylib 0x99509342 operator new[](unsigned long) + 17
10 rbframework.dylib 0x0094e4ee CreateCGImageFromPixMap(PixMap**, PixMap**, CGColorSpace*, bool) + 120
There are a few posts on this:
- http://www.monkeybreadsoftware.eu/listarchive-realbasic-nug/2012-12-20-7.shtml
- http://forums.realsoftware.com/viewtopic.php?f=1&t=43478
- http://www.realsoftwareblog.com/2011/01/managing-your-memory.html
There were 2 things that I was doing wrong, and a work around for the issue. First was that I was using the ListBox as a datastore of images. I did this because it’s easy to store images in the celltag. I also show a preview of the image in the listbox. I changed this implementation to just keep a reference to the absolute path of the file and then load it when it wants to be displayed. This cut the memory size down to 30MB after loading 100 images. The problem here though, was any changes to the listbox, it would refresh ALL cells, and thus, reading in all 100 images and drawing them would slow down the application considerably. I then changed it back to store the image in the celltag. Memory jumped up to 2GB, but the background painting of the images was instantaneous and the operation of the application was excellent.
The second was that when I was generating these collaged images, I was pulling the images out of the listbox, drawing them, and then nulling the image reference after it was saved to disk. This seemed to NOT clear the memory, and the consumption would keep climbing before it would crash (as per the error above). The way around it, was to use the absolute path when loading up the images to be laid out, and thus, the memory usage doesn’t keep climbing, but only fluctuates with an additional 100MB at most. It slows down the process slightly (as it is reading from disk and not memory), but keeps the application stable.
So I was using this (simplified), but it generated the crash:
dim myImage as Picture = PhotoListboxStore.celltag(row, column) p.Graphics.DrawPicture(myImage, x, y, w, h, 0, 0, myImage.Width, myImage.Height)
But instead, you should use this if you can:
dim myImage as Picture = GetFolderItem(imageAbsolutePath).OpenAsPicture p.Graphics.DrawPicture(myImage, x, y, w, h, 0, 0, myImage.Width, myImage.Height)
There are reasons for why this is happening in the linked posts, which I won’t get into. This was just a limitation I faced and worked around!