Memory leak with Array controller selectedObjects coerced to a record

I’m working on a small DVD library app for personal use only really. The app is just a simple table with five columns at present, which displays a list of movie titles with various other information. There’s also a few buttons which call up a web page to either IMDB or Netflix for the specific movie title selected. A search box is present. Additionally, any change to the table’s selection updates a text view with the synopsis of the selected movie. It all works, but its crashing in a couple of places. Both are related to using an Array Controller with the table. I followed Shane Stanley’s ApplescriptObjc Explored #4, which has been great. The problem, it seems, is that if i cause enough table selection changes to happen it will crash fairly predictably. It takes about 218 cycles before it dies, or with a single reload event it crashes immediately. I narrowed the crashing to the one line of code for the coercing of the returned selected object:
“set IpSelectionfromUI to UIArrayController’s selectedObjects() as record”

If i get rid of the “as record” bit… the crashing stops, but then i can’t use it this way, since the data being returned is basically a record, and needs to be coerced to that. I’m wondering though, if my line of code is too simple, and there’s actually more or maybe just something different that i should be doing to this.

The other crash is being caused by a button I added that is basically to just reload the Database again. I wanted this in case i make a backend change to the database information, and rather than quitting the app and relaunching it, i would rather be able to just hit a button and update it. The problem seems again related to the Array controller. As soon as it performs these steps a second time:
tell UIArrayController
removeObjects_(arrangedObjects())
addObjects_(IpTRec)
Particularly its the addObjects_(IpTRec) that seems to crash it, but its only doing this when i clear and then rebuild the IpTRec property with the full data from the DB. I experimented with loading just a single record into the property, and then redid the array controller steps again, and that does not crash it immediately, so it seems that there is a capacity related issue here.

It may also be worth mentioning that the DB contains about 1450 records, each with about 9 fields. Not all the fields are loaded yet, but most of it is used. Any help/thoughts on what might be causing this crashing would be greatly appreciated.

The crash itself is:

DVD Library Browser(2312,0x7fff72c54180) malloc: *** error for object 0x10926dba0: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug

Below is the whole script from the project: (If i’ve done anything stupid… i’m new to all this, so that’s my idiot disclaimer. :slight_smile: )

script AppDelegate
property parent : class “NSObject”

-- User Interface connected properties.
property UIArrayController : missing value
property UITable : missing value
property UISynopsis : missing value

-- Internal Properties.
property IpCdlt : ""
property IpDBfl : "~/Documents/db/DVD-Library.db"
property IpHttpImdbSearchHead : "http://www.imdb.com/find?q="
property IpHttpImdbSearchTail : "&s=all"
property IpHttpImdbTitle : "http://www.imdb.com/title/"
property IpHttpNetflixDVDMovie : "http://dvd.netflix.com/Movie/"
property IpHttpNetflixInstant : "http://dvd.netflix.com/WiPlayer?movieid="
property IpItem : ""
property IpFalse : false
property IpQuote : "'"
property IpSelectionfromUI : ""
property IpSpace : " "
property IpSqlc : ""
property IpSqld : ""
property IpTDat : ""
property IpTDt1 : ""
property IpTDt2 : ""
property IpTDt3 : ""
property IpTDt4 : ""
property IpTDt5 : ""
property IpTDt6 : ""
property IpTDt7 : ""
property IpTDt8 : ""
property IpTDt9 : ""
property IpTRec : {}
property IpTrue : true

-- Internal Properties for the DB fields.
property IpGenre : ""
property IpImdIndex : ""
property IpLibIndex : ""
property IpLibTitle : ""
property IpNfxDisc : ""
property IpNfxDuration : ""
property IpNfxIndex : ""
property IpNfxSynopsis : ""
property IpNfxTitle : ""
property IpNfxYear : ""
property IpViewed : ""

on applicationWillFinishLaunching_(aNotification)
    -- Get SQL data and populate it into the UI.
    loadSqlDataintoRecords()
end applicationWillFinishLaunching_

on applicationShouldTerminate_(sender)
	-- Insert code here to do any housekeeping before your application quits
	return current application's NSTerminateNow
end applicationShouldTerminate_

– this is called from a button.
on LookupInImdb_(sender)
if IpImdIndex is not “” then open location IpHttpImdbTitle & IpImdIndex
end LookupInImdb_

– also called from a button.
on LookupInNetflix_(sender)
if IpNfxIndex is not “” then open location IpHttpNetflixDVDMovie & IpNfxIndex
end LookupInNetflix_

– and another from a button.
on InstantInNetflix_(sender)
if IpNfxIndex is not “” then open location IpHttpNetflixInstant & IpNfxIndex
end InstantInNetflix_

– and one more button.
on ReloadDatabase_(sender)
loadSqlDataintoRecords()
end ReloadDatabase_

– called from two places
on loadSqlDataintoRecords()
set IpSqlc to “select IMDB_Index, Library_Index, Library_Title, Netflix_Disc, Netflix_Duration, Netflix_Index, Netflix_Title, Netflix_Year from Base”
set IpSqld to (do shell script “sqlite3” & IpSpace & IpDBfl & IpSpace & IpQuote & IpSqlc & IpQuote)
set IpCdlt to AppleScript’s text item delimiters – remember current delimiters before this routine.
set IpTRec to {}
set AppleScript’s text item delimiters to return
repeat with x from 1 to count of text items in IpSqld
set IpItem to text item x of IpSqld
set AppleScript’s text item delimiters to {“|”}
set IpTDt1 to text item 1 of IpItem
set IpTDt2 to text item 2 of IpItem
set IpTDt3 to text item 3 of IpItem
set IpTDt4 to text item 4 of IpItem
set IpTDt5 to text item 5 of IpItem
set IpTDt6 to text item 6 of IpItem
set IpTDt7 to text item 7 of IpItem
set IpTDt8 to text item 8 of IpItem
set AppleScript’s text item delimiters to return
set end of IpTRec to {RcImdIndex:IpTDt1, RcLibIndex:IpTDt2, RcLibTitle:IpTDt3, RcNfxDisc:IpTDt4, RcNfxDuration:IpTDt5, RcNfxIndex:IpTDt6, RcNfxTitle:IpTDt7, RcNfxYear:IpTDt8}
end repeat
set AppleScript’s text item delimiters to IpCdlt – reset delimiters to what it was before this routine.
– Update the UI Selection table.
tell UIArrayController
removeObjects_(arrangedObjects())
addObjects_(IpTRec)
setSelectionIndex_(0)
end tell
end loadSqlDataintoRecords

– the script is the table’s delegate so this routine can handle any change in selection on the table.
on TableViewSelectionDidChange_(aNotification)
updateIpAndUI()
end TableViewSelectionDidChange_

– this gets called each time there is a selection change on the table.
on updateIpAndUI()
–collect selection from Array controller
set IpSelectionfromUI to UIArrayController’s selectedObjects() as record
if count of IpSelectionfromUI = 8 then
– set internal properties when the proper result comes in from UI.
set IpNfxIndex to RcNfxIndex of IpSelectionfromUI
set IpImdIndex to RcImdIndex of IpSelectionfromUI
set IpSqlc to “select Netflix_Synopsis from Base where Library_Index='” & RcLibIndex of IpSelectionfromUI & IpQuote
set IpNfxSynopsis to do shell script “sqlite3” & IpSpace & IpDBfl & IpSpace & IpQuote & IpSqlc & IpQuote
else
– reset internal properties to blank when improper result comes in from UI.
–set IpGenre to “”
set IpImdIndex to “”
–set IpLibIndex to “”
–set IpLibTitle to “”
–set IpNfxDisc to “”
–set IpNfxDuration to “”
set IpNfxIndex to “”
set IpNfxSynopsis to “”
–set IpNfxTitle to “”
–set IpNfxYear to “”
–set IpViewed to “”
end if
– Update UI elements
tell UISynopsis to setString_(IpNfxSynopsis)
end updateIpAndUI

end script

Are you using garbage collection or ARC?

I’ve tried garbage collection, but the compiler doesn’t let me use this. I’ve tried ARC, and that doesn’t stop the problems either.

Shane,

Good news! I went back into the build settings of my project, and using one of your sample scripts, matched every setting to what yours have. BLAM! Garbage collection is working now and the hard crashing has been cured!
I really needed GCC, since i have one Snow machine left in the house that can’t upgrade to Lion. (older white iMac)

There is still an error popping that looks like this:

DVD Library Browser(8544,0x7fff72c54180) malloc: reference count underflow for 0x400562800, break on auto_refcount_underflow_error to debug.

Not sure if i need to worry about it, since the app seems to function now, however i’ve not actually built it yet. Maybe this error will be more significant at that point?

I also wonder if i didn’t quite have ARC set properly. Obviously, build settings are very relevant to app stability.

Thank you for the help and the book!