OC 内存管理问题

发布于 2022-09-12 04:47:17 字数 1066 浏览 26 评论 0

最近学习 OC 内存管理遇到个问题

main.m

int main(int argc, const char * argv[]) {
  Person *p1 = [[Person alloc] init];
  Person *p2 = [[Person alloc] init];
  Dog *d = [[Dog alloc] init];

  p1.dog = d;
  p2.dog = d;
  [d release];

  p1.dog = nil;
  p2.dog = nil;
  return 0;
}

Dog.m

@implementation Dog

- (void)dealloc
{
  NSLog(@"Dog 被销毁了");
  [super dealloc];
}

@end

Person.h

@class Dog;
@interface Person : NSObject

@property(retain) Dog *dog;

@end

上面的代码运行后,可以打印出 Dog 被销毁了。但是如果把 main.m 改成下面的代码就没有打印了。

int main(int argc, const char * argv[]) {
  Person *p1 = [[Person alloc] init];
  Person *p2 = [[Person alloc] init];
  Dog *d = [[Dog alloc] init];

  p1.dog = d;
  p2.dog = p1.dog;  // 只改了这一行
  [d release];

  p1.dog = nil;
  p2.dog = nil;
  return 0;
}

感觉这个问题可能和内存管理没什么关系,可能是变量引用的问题,初学 OC 希望大佬们指点下~

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

放血 2022-09-19 04:47:17

问题应该出在这里

@property(retain) Dog *dog;

dog属性声明为了atomic类型,为了保证原子性,dog的set和get方法应该做过处理。
我感觉mrc下的atomic属性的set和get方法应该类似下面这样实现。

- (Dog *) dog {
    Dog *d = nil;
     @synchronized(self) {
        d = [[_dog retain] autorelease];
    }
     return d;
}

- (void)setDog:(Dog *)dog {
    @synchronized(self) {
        [dog retain];
        [_dog release];
        _dog = dog;
    }
}

所以在调用p2.dog = p1.dog;的时候,会先调用get方法(p1.dog),内部会先对dog retain一次,引用计数+1, 然后放进自动释放池,在调用set(p2.dog)时,又会retain一次。所以这一句代码引用计数其实是+2了, 所以最后在release和nil之后,引用计数仍然为1,不会释放。

按道理说在get里面+1的那一次应该被减回去的,但是因为main方法中的autoreleasepool被删掉了,所以标记的autorelease没有起到作用。

综上,atomic的get方法中为了安全多+1并没有被autorelease掉,所以导致引用计数无法被置0,属性无法释放,也就不会打印dealloc.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文