3

Using ARC, the following examples all have memory leaks as the result of an exception being raised that have dynamic content. It is no surprise that the dynamic content has not been released because the exception prevents the normal return of the function. These memory leaks are really not a big issue, since exceptions should be used sparingly such as when an application fails without chance of recovery. I just want to make sure there there is not some way to release the memory that I am currently unaware of.


- (void)throwsException
{
    NSString *dynamicContent = [NSString stringWithFormat:@"random value[%d]", arc4random() % 100];
    [NSException raise:@"Some random thing" format:@"%@", dynamicContent];
}

The following two examples us the above method throwsException to throw the exception to make the example less contrived.

- (void)test_throwsException_woAutoreleasepool
{
    @try
    {
        [self throwsException];
        NSLog(@"No exception raised.");
    }
    @catch (NSException *exception)
    {
        NSLog(@"%@ - %@", [exception name], [exception reason]);
    }
}

Note the use of @autoreleasepool, still has memory leaks.

- (void)test_throwsException_wAutoreleasepool
{
    @autoreleasepool {
        @try
        {
            [self throwsException];
            NSLog(@"No exception raised.");
        }
        @catch (NSException *exception)
        {
            NSLog(@"%@ - %@", [exception name], [exception reason]);
        }
    }
}

Same as the above example, just more contrived by raising the exception directly in the try block.

- (void)test_consolidated_raiseFormat
{
    @autoreleasepool {
        @try
        {
            NSString *dynamicContent = [NSString stringWithFormat:@"random value[%d]", arc4random() % 100];
            [NSException raise:@"Some random thing" format:@"%@", dynamicContent];
            NSLog(@"No exception raised.");
        }
        @catch (NSException *exception)
        {
            NSLog(@"%@ - %@", [exception name], [exception reason]);
        }
    }
}

This example uses exceptionWithName. No expected differences.

- (void)test_consolidated_exceptionWithName
{
    @autoreleasepool {
        @try
        {
            NSString *dynamicContent = [NSString stringWithFormat:@"random value[%d]", arc4random() % 100];
            NSException *exception = [NSException exceptionWithName:@"Some random thing"
                                                             reason:dynamicContent
                                                           userInfo:nil];
            [exception raise];
            NSLog(@"No exception raised.");
        }
        @catch (NSException *exception)
        {
            NSLog(@"%@ - %@", [exception name], [exception reason]);
        }
    }
}

This example uses initWithName. No expected differences.

- (void)test_consolidated_initWithName
{
    @autoreleasepool {
        @try
        {
            NSString *dynamicContent = [NSString stringWithFormat:@"random value[%d]", arc4random() % 100];
            NSException *exception = [[NSException alloc] initWithName:@"Some random thing"
                                                                reason:dynamicContent
                                                              userInfo:nil];
            [exception raise];
            NSLog(@"No exception raised.");
        }
        @catch (NSException *exception)
        {
            NSLog(@"%@ - %@", [exception name], [exception reason]);
        }
    }
}
mmorris
  • 4,006
  • 3
  • 27
  • 29

1 Answers1

0

It would seem that NSException is fundamentally incompatible with ARC. Judging by the fact that these exceptions were not implemented in Swift, for that same reason. I would be interested to know why you think that the leak is triggered by attaching the item to the exception, rather than it simply having a retain count of "1" prior to the raise event.

Think about it - NSException is an object, and its selector can be passed dynamically, so the compiler wouldn't be right to interpret "raise" as a language feature event. Therefore, no ARC release instructions are added at that particular place.

Update - here is another explanation

Why does "try catch" in Objective-C cause memory leak?

Community
  • 1
  • 1
user1122069
  • 1,767
  • 1
  • 24
  • 52