User Defaults and memory leak

When I build an application in AppleScript Studio (Xcode 2.2, GCC 3.3 or 4.0.1, Mac OS X 10.4.3) and use the “user defaults” object from AppleScript to register and read my settings, according to MallocDebug, I get a memory leak of 16 bytes per default. To illustrate this, here is a link to a project that simply maintains 10 defaults (the defaults are standard AppleScript classes: boolean, integer, real, string, date, list, & record):

http://homepage.mac.com/jonn8/as/dist/UserDefaults.zip

When it is launched from MallocDebug (Xcode > Debug > Launch Using Performance Tool > MallocDebug), after it runs, if I check for leaks, I see that MallocDebug reports a 160 byte leak. This is vanilla AppleScript Studio code. Can others confirm that there is a leak? When writing & reading the settings a second time (there’s a button in the main window for this), MallocDebug reports a second leak of 76 bytes but additional writes & reads don’t increase the leak. Is there any remedy? The leak is a few bytes in this project and it doesn’t appear that the leak grows but on another application I have that uses the same code, I have a lot more defaults and the leak does seem to grow when reading/writing the settings.

Thanks,
Jon

Jon,

I do see a leak, too. I’m getting an initial allocation of 144 bytes, and then an additional allocation of 72 bytes when the defaults are set… for a grand total of only 216 bytes for the app (even for repeated invocations). I’m guessing that if I went back though my old projects that I’d find a lot of ‘leaks’ that are similar in nature to this. In reality, a couple hunder’d bytes that cap off at a finite maximum is a bearable leak… and I wouldn’t worry about it. If it is in fact a leak that builds indefinitely, then you’re probably going to want to resolve the issue.

I’m also seeing this problem with my LibrarySE plugin, and it appears somehow related to the allocation of applescript objects. The entire plugin is obj-c, but I use nsapplescript objects to handle interactions with external apps. Whenever I make a call to an nsapplescript object, I get a mammary leak (according to mallocdebug). But the memory does not grow on repeated calls, and appears to be freed when the process terminates. In my opinion, the behavior of the test proj is acceptable… but the behavior you describe of your real app may need some attention. As usual, let me know if I can help with the real deal.

j

PS - Your project uses the 10.4u.sdk which I don’t have. This led me to get some build errors, and I wasn’t able to build until I removed the root sdk entry of the project and the target in the settings and rebuild. If others get this error, that’s why.

By coincidence, I read the Growl forum post here shortly after reading this one. A quick skim through will see two mentions of AppleScript and Xcode as leakers in general.

Thanks for the offer to help. Yes, I noticed this too when I tried to build the project as a release build instead of the debug build. I use GCC 3.3 so my apps are still 10.2-compatible and it choked when I tried to build the app. For me I only had to remove the i863 architecture listing (I had the 10.4 SKD installed).

Using my app normally and running “leaks -nocontext AppName” from the Terminal gives me a little more comfort (sort of). As I use my app, leaks notes 4720 total leaked bytes. Using the app for a little bit longer and checking with leaks periodically, it ranges from 3968 total leaked bytes to 5088 (this is the largest number I’ve observed). I’m comforted that my leaks are not run away and that they might not actually be leaks. How can there be leaks with the leaked memory decreases from time to time (without restarting the app)?

Incidentally, I know that I have to use leaks or MallocDebug to check the memory usage, Activity Monitor is not accurate for this type of thing. However, my users use Activity Monitor and alarmed by the memory usage (it usually hovers around 50MB or real memory) but checking allocation with leaks, the memory footprint is much, much smaller (about 15MB). So, what is Activity Monitor actually monitoring?

Jon

Rewriting the project to use Obj-C for registering, reading, and writing the defaults (using a custom method class called from the AppleScript) eliminates the initial leak. Here’s the link to the revised project (which should also compile for Xcode 2.1):

http://homepage.mac.com/jonn8/as/dist/UserDefaults.zip
(If you downloaded recently, Option-Click on the link to make sure you get the latest version, not one cached by your browser.)

I still get a small leak (76 bytes) in MallocDebug when I write & read the defaults a second time but it doesn’t grow subsequently. When I run the release version on its own (not from Xcode or MallocDebug) and then use leaks in the Terminal (leaks UserDefaults), I get “3 leaks for 320 total leaked bytes” but it doesn’t grow as I write & read subsequently.

Jon

I see pretty much what you’re seeing. I do get a bit higher leak counts with terminal (7 leaks for 726 bytes) but still within reasonable limits and not too concerning at less than 1k. I of course can’t speak for your real-world implementations, but you seem to be doing all you can do.

As far as Activity Monitor goes, I can only speculate… but here are my thoughts. Different allocations happen for different reasons. When memory is allocated, it’s either done so for a set size block, or dynamically depending on what is actually needed. The 50mb you’re seeing may be set by the application object automatically (and largely beyond your control) to fill a reasonably-sized maximum memory usage. The test project certainly doesn’t show any abnormal “activity”, but your real app could be different. Also, memory may be somehow split between different parts of the entire memory space, and maybe activity monitor sucks at keeping track of how much memory is actually “in use” by the app, counting dead space and other allocations against your overall ‘footprint’. I used terminal, malloc, and always have menumeters running, and don’t see anything out of the ordinary.

Honestly, if your users are savvy (and paranoid) enough to use activity monitor and other debugging tools, they should be understanding in seeing that every app has a footprint of some kind. Given that your apps are pretty professional and many are widely distributed, their functionality should speak for itself in justifying a bit of memory usage. Your changes dropped the leaked bytes significantly. and even if you launched your app a thousand times and the memory was NOT freed, you’d still be only a couple hundred k in the hole… a problem easily remedied by an occassional restart. I have gobs of apps (especially ones like xcode or firefox) that slowly leak memory, forcing me to restart every few days to clear out 100-200 MB of junk. I wouldn’t lose sleep over a couple bytes of leaked applescript memory, that seems to be returned after termination. Anyone who does is probably living in a plastic bubble and is addicted to cranberry enemas. :cool:

j

Thanks for reassuring me. I’m revising some of my apps. In particular, I’ve made JPT a much better behaved app in terms of memory. Since most users who use it keep it open all the time, it has to keep its memory in check. For the most part the current release is OK but for users who use the Address Book numbers menus (there are options for concurrently displaying the content in a number of ways: alphabetical, by group, by company, etc.), it can get a little unruly. For some users with a ton of contacts in their Address Book (I get notes all the time from people who have 2,000+ contacts!), each contact can have several phone numbers and with all of the different submenu options enabled, JPT could build 20,000+ menu items! Further, it rebuilds these menus anytime that the Address Book is modified. Each menu item (by default but optional) has an image and when rebuilding in the current release, not all of those images are properly released. In the new version, they are which eliminates a huge leak. The new defaults routines have helped with the footprint in general.

Thanks again, as always, for your time and thoughtful discussion & advice. Not to mention the humor. Cranberries, really?

Jon