【问题标题】:ARC memory leaks as the result of raising a NSException with dynamic content使用动态内容引发 NSException 导致 ARC 内存泄漏
【发布时间】:2013-05-26 13:17:19
【问题描述】:

使用 ARC,以下示例都会由于引发具有动态内容的异常而导致内存泄漏。动态内容没有发布也就不足为奇了,因为异常阻止了函数的正常返回。这些内存泄漏确实不是一个大问题,因为应该谨慎使用异常,例如当应用程序失败而没有恢复机会时。我只是想确保没有任何方法可以释放我目前不知道的内存。


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

下面两个例子使用上面的方法throwsException抛出异常,让例子不那么做作。

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

注意@autoreleasepool的使用,还是有内存泄漏。

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

与上面的示例相同,只是在try 块中直接引发异常更加人为。

- (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]);
        }
    }
}

此示例使用exceptionWithName。没有预期的差异。

- (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]);
        }
    }
}

此示例使用initWithName。没有预期的差异。

- (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]);
        }
    }
}

【问题讨论】:

    标签: objective-c exception automatic-ref-counting


    【解决方案1】:

    似乎 NSException 从根本上与 ARC 不兼容。出于同样的原因,从这些异常没有在 Swift 中实现的事实来看。我很想知道您为什么认为泄漏是通过将项目附加到异常来触发的,而不是在引发事件之前仅保留计数为“1”。

    考虑一下 - NSException 是一个对象,它的选择器可以动态传递,所以编译器将“raise”解释为语言特性事件是不对的。因此,在该特定位置没有添加任何 ARC 发布说明。

    更新 - 这是另一种解释

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-15
      • 1970-01-01
      • 2013-03-19
      • 2016-02-04
      • 2012-04-03
      • 2021-09-02
      相关资源
      最近更新 更多