C语言中内存泄露的例子,内存泄露实例

object->block->object(对象强引用块,块中捕获对象)

@interface TestViewController ()

@property (copy, nonatomic) void(^testMemeoryLeakBlock)(void);

@property (copy, nonatomic) NSString* aStr;

@end

@implementation TestViewController

- (void)viewDidLoad {

[super viewDidLoad];

self.aStr = @"test string";

__weak typeof(self) weakSelf = self;

self.testMemeoryLeakBlock = ^{

NSLog(@"%@",self.aStr);

NSLog(@"%@",_aStr); //block 也会捕获带下划线变量中self,

__strong typeof(weakSelf) strongSelf = weakSelf;

NSLog(@"%@",strongSelf.aStr);

NSLog(@"%@",strongSelf->_aStr);

};

}

- (void)dealloc{

//重写dealloc方法,观察对象是否被释放.

NSLog(@"dealloc method excute!");

}

[NSNotificationCenter defaultCenter]addObserverForName......

[NSNotificationCenter defaultCenter]addObserverForName...其实严格中没有出现循环引用,只是因为强引用造成对象无法释放.

@interface TestViewController ()

@property (strong, nonatomic) id observer;

@end

@implementation TestViewController

- (void)viewDidLoad {

[super viewDidLoad];

// Do any additional setup after loading the view.

}

- (void)viewWillAppear:(BOOL)animated{

[super viewWillAppear:animated];

//这里使用weakSelf时候,可以不用移除观察者.

__weak typeof(self) weakSelf = self;

self.observer =

[[NSNotificationCenter defaultCenter]addObserverForName:UIKeyboardDidHideNotification

object:nil

queue:[NSOperationQueue mainQueue]

usingBlock:^(NSNotification * _Nonnull note) {

__strong typeof(weakSelf) strongSelf = weakSelf;

[strongSelf doSomeThing];

}];

}

- (void)viewWillDisappear:(BOOL)animated{

[super viewWillDisappear:animated];

[[NSNotificationCenter defaultCenter]removeObserver:self.observer];

self.observer = nil; //如果是Strong 同时必须置nil

//[NSNotificationCenter defaultCenter]-->Observer --CopyBlock-->Self

}

- (void)dealloc{

NSLog(@"ViewController Dealloc!");

}

- (void)doSomeThing{

}

NSTimer scheduledTimerWithTimeInterval.....

NSTimer会保留其目标对象;知道定时器失效为止,调用invalidate方法可令timer失效,另外

一次性的timer任务执行完也会失效;反复执行的任务容易出现循环引用,如果其他对象又保留

timer一定会引入循环引用,可以引入块来打破这种保留环.

@interface NSTimer (invoke)

+(NSTimer*)scheduledTimerWithTimeInterval:(NSTimeInterval)ti

block:(void(^)())block

userInfo:(id)userInfo

repeats:(BOOL)yesOrNo;

@end

@implementation NSTimer (ste_invoke)

+(NSTimer*)scheduledTimerWithTimeInterval:(NSTimeInterval)ti

block:(void(^)())aBlock

userInfo:(id)userInfo

repeats:(BOOL)yesOrNo

{

return [

self scheduledTimerWithTimeInterval:ti

target:self

selector:@selector(ste_timerFireMethod:)

userInfo:[aBlock copy ]

repeats:yesOrNo

];

}

+(void)ste_timerFireMethod:(NSTimer*)timer

{

void(^block)() = timer.userInfo;

if (block) {

block();

}

}

@end

//使用的时候;也应该注意块的循环引用

Core Foundation 对象的内存管理

我们创建的Core Foundation 对象在ARC下由我们自己管理其生命周期(创建了就要对应有释放),当转换为Foundation框架下的对象时涉及到的对象方法有:

__bridge: 只做类型转换,不修改相关对象的引用计数,原来的Core Foundation 对象在不用时,需要调用CFRelease 方法.

__bridge_retained:类型转换后,将相关对象的引用计数加 1,原来的 Core Foundation 对象在不用时,需要调用CFRelease 方法.

__bridge_transfer:类型转换后,将该对象的引用计数交给ARC管理, Core Foundation 对象在不用时,不再需要调用 CFRelease 方法.

about block

bVU4EK?w=500&h=500

对应的数据结构如下:

struct Block_descriptor {

unsigned long int reserved;

unsigned long int size;

void (*copy)(void *dst, void *src);

void (*dispose)(void *);

};

struct Block_layout {

void *isa;

int flags;

int reserved;

void (*invoke)(void *, ...);

struct Block_descriptor *descriptor;

/* Imported variables. */

};

各个字段解释:

isa 指针,所有对象都有该指针,用于实现对象相关的功能.

flags,用于按 bit 位表示一些 block 的附加信息,本文后面介绍 block copy 的实现代码可以看到对该变量的使用.

reserved,保留变量.

invoke,函数指针,指向具体的 block 实现的函数调用地址.

descriptor, 表示该 block 的附加描述信息,主要是 size 大小,以及 copy 和 dispose 函数的指针.

variables,capture 过来的变量,block 能够访问它外部的局部变量,就是因为将这些变量(或变量的地址)复制到了结构体中.

在 Objective-C 语言中,一共有 3 种类型的 block:

_NSConcreteGlobalBlock 全局的静态 block,不会访问任何外部变量.

_NSConcreteStackBlock 保存在栈中的 block,当函数返回时会被销毁.

_NSConcreteMallocBlock 保存在堆中的 block,当引用计数为 0 时会被销毁.

对于block外的变量引用,block默认是将其复制到其数据结构中来实现访问的

对于用 __block 修饰的外部变量引用,block 是复制其引用地址来实现访问的(能够修改值)

在 ARC 开启的情况下,将只会有 NSConcreteGlobalBlock 和 NSConcreteMallocBlock 类型的 block

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值