Memory leaks when running an apple event

  • Hi all,

    I'm trying to create an simple application using Apple Events to see if
    a specified application is running (iTunes in my case). A thread from
    main.m will use the mainProcess method so the script will run every
    second. The problem I'm having is that the NSAppleEventDescriptor i'm
    using (result) isn't deallocated and the every 100 secs it grows with
    1Mb of memory. Can someone help me please ... I've tried release,
    dealloc, autorelease and isn't working. Please if you know give me some
    ideas how to solve this problem in cocoa. Thanx guys.

    This is the code I'm using:

    -(void)isAppRunning
    {

        NSString* appleEventString = [NSString stringWithFormat:@"set
    itunes_active to false\n with timeout of 1 second\n tell application
    \"Finder\"\n if (get name of every process) contains \"iTunes\" then set
    itunes_active to true\n end tell\n end timeout\n return itunes_active"];
        NSAppleScript *script = [[NSAppleScript alloc]
    initWithSource:appleEventString];
        NSDictionary *errorInfo;
        NSAppleEventDescriptor* result;
        result = [script executeAndReturnError:errorInfo];

        NSLog(@"%@", [result stringValue]);

        [result dealloc];
        [script dealloc];
    }

    -(void)mainProcess:(id)anObject
    {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

        while (1)
        {
            [self isAppRunning];
        }

        [pool release];
    }
  • On Oct 12, 2007, at 11:13 AM, Alex Bumbu wrote:

    > Hi all,
    >
    > I'm trying to create an simple application using Apple Events to
    > see if a specified application is running (iTunes in my case). A
    > thread from main.m will use the mainProcess method so the script
    > will run every second. The problem I'm having is that the
    > NSAppleEventDescriptor i'm using (result) isn't deallocated and the
    > every 100 secs it grows with 1Mb of memory. Can someone help me
    > please ... I've tried release, dealloc, autorelease and isn't
    > working. Please if you know give me some ideas how to solve this
    > problem in cocoa. Thanx guys.
    >
    > This is the code I'm using:
    >
    > -(void)isAppRunning
    > {
    > NSString* appleEventString = [NSString stringWithFormat:@"set
    > itunes_active to false\n with timeout of 1 second\n tell
    > application \"Finder\"\n if (get name of every process) contains
    > \"iTunes\" then set itunes_active to true\n end tell\n end timeout
    > \n return itunes_active"];
    > NSAppleScript *script = [[NSAppleScript alloc]
    > initWithSource:appleEventString];
    > NSDictionary *errorInfo;
    > NSAppleEventDescriptor* result;
    > result = [script executeAndReturnError:errorInfo];
    >
    > NSLog(@"%@", [result stringValue]);
    > [result dealloc];
    > [script dealloc];
    > }
    >
    > -(void)mainProcess:(id)anObject
    > {
    > NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    > while (1)
    > {
    > [self isAppRunning];
    > }
    > [pool release];
    > }

    You shouldn't be calling dealloc yourself. That is up to Cocoa to
    deal with. You should review the memory management guide several
    times (from my experience it takes awhile to start to understand.

    http://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/
    index.html
  • Alex Bumbu wrote:

    > I'm trying to create an simple application using Apple Events to
    > see if
    > a specified application is running (iTunes in my case).

    General question: why do you want to use AppleScript for this? Just
    call [[NSWorkspace sharedWorkspace] launchedApplications] and look
    for the desired process in the resulting NSArray, or you could use
    the Carbon Process Manager (GetNextProcess + GetProcessBundleLocation/
    GetProcessInformationCopyDictionary) if you prefer.

    has
    --
    http://appscript.sourceforge.net
    http://rb-appscript.rubyforge.org
  • On Fri, 12 Oct 2007 11:38:58 -0400, Paul Bruneau wrote:

    > On Oct 12, 2007, at 11:13 AM, Alex Bumbu wrote:
    >
    >
    >> Hi all,
    >>
    >> I'm trying to create an simple application using Apple Events to
    >> see if a specified application is running (iTunes in my case). A
    >> thread from main.m will use the mainProcess method so the script
    >> will run every second. The problem I'm having is that the
    >> NSAppleEventDescriptor i'm using (result) isn't deallocated and the
    >> every 100 secs it grows with 1Mb of memory. Can someone help me
    >> please ... I've tried release, dealloc, autorelease and isn't
    >> working. Please if you know give me some ideas how to solve this
    >> problem in cocoa. Thanx guys.
    >>
    >> This is the code I'm using:
    >>
    >> -(void)isAppRunning
    >> {
    >> NSString* appleEventString = [NSString stringWithFormat:@"set
    >> itunes_active to false\n with timeout of 1 second\n tell
    >> application \"Finder\"\n if (get name of every process) contains
    >> \"iTunes\" then set itunes_active to true\n end tell\n end timeout
    >> \n return itunes_active"];
    >> NSAppleScript *script = [[NSAppleScript alloc]
    >> initWithSource:appleEventString];
    >> NSDictionary *errorInfo;
    >> NSAppleEventDescriptor* result;
    >> result = [script executeAndReturnError:errorInfo];
    >>
    >> NSLog(@"%@", [result stringValue]);
    >> [result dealloc];
    >> [script dealloc];
    >> }
    >>
    >> -(void)mainProcess:(id)anObject
    >> {
    >> NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    >> while (1)
    >> {
    >> [self isAppRunning];
    >> }
    >> [pool release];
    >> }
    >
    > You shouldn't be calling dealloc yourself. That is up to Cocoa to
    > deal with. You should review the memory management guide several
    > times (from my experience it takes awhile to start to understand.
    >
    > http://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/
    > index.html

    Two things:

    (1) [script release] is what you want to call, as following Paul's
    suggesting will reveal.

    (2) It's also possible that Mac OS X, when running the script,
    retains and autoreleases quite a bit of memory; this won't get freed
    until the surrounding pool gets released; note that your autorelase
    pool doesn't actually get released until the loop (which runs
    forever) returns.  Put another allocation and release of an
    autorelease pool inside the "while (1)" loop, around the call to  to
    free this stuff.

    Rudi
  • On Fri, 12 Oct 2007 11:38:58 -0400, Paul Bruneau wrote:

    > On Oct 12, 2007, at 11:13 AM, Alex Bumbu wrote:
    >
    >
    >> Hi all,
    >>
    >> I'm trying to create an simple application using Apple Events to
    >> see if a specified application is running (iTunes in my case). A
    >> thread from main.m will use the mainProcess method so the script
    >> will run every second. The problem I'm having is that the
    >> NSAppleEventDescriptor i'm using (result) isn't deallocated and the
    >> every 100 secs it grows with 1Mb of memory. Can someone help me
    >> please ... I've tried release, dealloc, autorelease and isn't
    >> working. Please if you know give me some ideas how to solve this
    >> problem in cocoa. Thanx guys.
    >>
    >> This is the code I'm using:
    >>
    >> -(void)isAppRunning
    >> {
    >> NSString* appleEventString = [NSString stringWithFormat:@"set
    >> itunes_active to false\n with timeout of 1 second\n tell
    >> application \"Finder\"\n if (get name of every process) contains
    >> \"iTunes\" then set itunes_active to true\n end tell\n end timeout
    >> \n return itunes_active"];
    >> NSAppleScript *script = [[NSAppleScript alloc]
    >> initWithSource:appleEventString];
    >> NSDictionary *errorInfo;
    >> NSAppleEventDescriptor* result;
    >> result = [script executeAndReturnError:errorInfo];
    >>
    >> NSLog(@"%@", [result stringValue]);
    >> [result dealloc];
    >> [script dealloc];
    >> }
    >>
    >> -(void)mainProcess:(id)anObject
    >> {
    >> NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    >> while (1)
    >> {
    >> [self isAppRunning];
    >> }
    >> [pool release];
    >> }
    >
    > You shouldn't be calling dealloc yourself. That is up to Cocoa to
    > deal with. You should review the memory management guide several
    > times (from my experience it takes awhile to start to understand.
    >
    > http://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/
    > index.html

    Two things:

    (1) [script release] is what you want to call, as following Paul's
    suggesting will reveal.

    (2) It's also possible that Mac OS X, when running the script,
    retains and autoreleases quite a bit of memory; this won't get freed
    until the surrounding pool gets released; note that your autorelase
    pool doesn't actually get released until the loop (which runs
    forever) returns.  Put another allocation and release of an
    autorelease pool inside the "while (1)" loop, around the call to  to
    free this stuff.

    Rudi
  • Thanx for the reply. I've made the modifications u've recomended to me but
    the problem still exists. I've found that the NSAppleEventDescriptor *result
    consumes the memory, but if i try to release it the application will crash.
    I've tested with this example from apple
    http://developer.apple.com/technotes/tn2006/tn2084.html but i'm having the
    same problem.

    Here is the code i'm using now:

    -(void)isAppRunning
    {
      NSDictionary* errorInfo;
      NSAppleEventDescriptor* result;

      NSString* appleEventString = [NSString stringWithFormat:@"set
    itunes_active to false\n with timeout of 1 second\n tell application
    \"Finder\"\n if (get name of every process) contains \"iTunes\" then set
    itunes_active to true\n end tell\n end timeout\n return itunes_active"];
      NSAppleScript *script = [[NSAppleScript alloc]
    initWithSource:appleEventString];

      result = [script executeAndReturnError:&errorInfo];

      NSLog(@"%@", [result stringValue]);

      [script release];
    }

    -(void)mainProcess:(id)anObject
    {
      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

      while (1)
      {
          NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
          [self isAppRunning];
          [pool release];
      }

      [pool release];
    }
  • Alex Bumbu wrote:

    > Thanx for the reply. I've made the modifications u've recomended to
    > me but
    > the problem still exists. I've found that the
    > NSAppleEventDescriptor *result
    > consumes the memory, but if i try to release it the application
    > will crash.

    As-per Cocoa memory management rules, the NSAppleEventDescriptor
    returned by [NSAppleScript -executeAndReturnError:] is autoreleased
    and will be dealloced when the current autorelease pool is disposed
    of. Don't release it yourself or you'll get a memory error when the
    autorelease pool tries to release it when it's already been dealloced.

    As for the leaks you're currently observing, I would hazard those are
    coming from NSAppleScript itself. Google 'NSAppleScript memory leak'
    for similar discussions.

    Other comments:

    1. Your script doesn't change between calls, so you only really need
    to create a single NSAppleScript instance, assign it to a static
    variable and reuse it each time. That may or may not minimise the
    leakage, depending on exactly where it's coming from.

    2. If your application is intended for public use you should really
    avoid scripting the Finder where possible, since not all OS X users
    will have it running and those that don't (e.g. Path Finder users)
    won't appreciate you launching it. e.g. Use System Events Process
    Suite instead.

    3. If you want to script applications from ObjC+Cocoa, take a look at
    objc-appscript <http://appscript.sourceforge.net/objc-appscript.html>
    which provides a high-level wrapper around the Apple Event Manager
    API, avoiding the AppleScript language and its related headaches
    completely.

    4. Using application scripting to check for a running process is
    unnecessarily complex; just use NSWorkspace or the Carbon Process
    Manager.

    HTH

    has
    --
    http://appscript.sourceforge.net
    http://rb-appscript.rubyforge.org
previous month october 2007 next month
MTWTFSS
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31        
Go to today