Skip to content

Instantly share code, notes, and snippets.

@sodastsai
Last active October 12, 2016 23:44
Show Gist options
  • Save sodastsai/a071e3b961000a3148eb5ecae4a0558b to your computer and use it in GitHub Desktop.
Save sodastsai/a071e3b961000a3148eb5ecae4a0558b to your computer and use it in GitHub Desktop.
Auto release pool
#import <Foundation/Foundation.h>
// Assume -fno-objc-arc ... 假設沒 ARC
@interface MyObject: NSObject
@end
@implementation MyObject
- (NSArray *)someMethodReturnArray1 {
NSMutableArray *array = [[NSMutableArray alloc] init]; // 有 `alloc` 就要有 `release` or `autorelease`
// ... 做些事
return array; // gg, 沒 release
}
- (NSArray *)someMethodReturnArray2 {
NSMutableArray *array = [[NSMutableArray alloc] init]; // 有 `alloc` 就要有 `release` or `autorelease`
// ... 做些事
[array release];
return array; // gg, 吐垃圾給別人幹嘛
}
- (NSArray *)someMethodReturnArray3 {
NSMutableArray *array = [[NSMutableArray alloc] init]; // 有 `alloc` 就要有 `release` or `autorelease`
// ... 做些事
return array;
[array release]; // gg, 沒 release, 這行怎可能跑到
}
- (NSArray *)someMethodReturnArray4 {
NSMutableArray *array = [[NSMutableArray alloc] init]; // 有 `alloc` 就要有 `release` or `autorelease`
// ... 做些事
return [array autorelease]; // ok, 把 array 放到 auto release pool, 等等再收
}
- (NSArray *)newArray {
NSMutableArray *array = [[NSMutableArray alloc] init]; // 有 `alloc` 就要有 `release` or `autorelease`
// ... 做些事
return array; // ok
/*
* 因為 Objective-C 的 convention 說 名字有 new, copy, init, alloc 的 method
* call 的人要負責把拿到的東西給 release
*/
}
@end
#import <Foundation/Foundation.h>
// Assume -fno-objc-arc ... 假設沒 ARC
//
// 存成 `main.m` 然後在 Terminal 跑 `clang -framework Foundation -fno-objc-arc -o main main.m && ./main && rm main`
// 然後在 `./main` 就會動囉
//
// ---------------------------------------------------------------------------------------------------------------------
@interface MyObject: NSObject
@property (nonatomic, retain, readonly) NSString *name;
- (instancetype)initWithName:(NSString *)name;
@end
@implementation MyObject
- (instancetype)initWithName:(NSString *)name {
if (self = [super init]) {
_name = name;
NSLog(@">>> %@ created.", _name);
}
return self;
}
- (void)dealloc {
NSLog(@"<<< %@ bye.", self.name);
[super dealloc];
}
- (instancetype)autorelease {
NSLog(@"--- %@ 被放到 autoreleasepool 了", self.name);
return [super autorelease];
}
@end
// ---------------------------------------------------------------------------------------------------------------------
int main(int argc, char *argv[]) {
@autoreleasepool {
{
NSLog(@"開始吧");
MyObject *barry = [[MyObject alloc] initWithName:@"Barry"];
MyObject *richard = [[[MyObject alloc] initWithName:@"Richard"] autorelease];
NSLog(@"收掉Barry");
[barry release], barry = nil; // Barry 真的被收掉了 但指標還在
NSLog(@"Scope 要結束囉");
} // barry/richard 兩個指標都沒了, 但 Richard 還在, 還沒被收
NSLog(@"Scope 已經結束囉");
NSLog(@"Auto release pool 要結束囉");
} // Richard 終於被收掉了
NSLog(@"Auto release pool 已經結束囉");
return 0;
}
/*
我的執行結果
---
2016-10-13 07:39:53.749 main[6276:4616698] 開始吧
2016-10-13 07:39:53.750 main[6276:4616698] >>> Barry created.
2016-10-13 07:39:53.750 main[6276:4616698] >>> Richard created.
2016-10-13 07:39:53.750 main[6276:4616698] --- Richard 被放到 autoreleasepool 了
2016-10-13 07:39:53.750 main[6276:4616698] 收掉Barry
2016-10-13 07:39:53.750 main[6276:4616698] <<< Barry bye.
2016-10-13 07:39:53.750 main[6276:4616698] Scope 要結束囉
2016-10-13 07:39:53.750 main[6276:4616698] Scope 已經結束囉
2016-10-13 07:39:53.750 main[6276:4616698] Auto release pool 要結束囉
2016-10-13 07:39:53.750 main[6276:4616698] <<< Richard bye.
2016-10-13 07:39:53.750 main[6276:4616698] Auto release pool 已經結束囉
---
*/
#import <Foundation/Foundation.h>
// -fno-objc-arc 假設沒 ARC
int main(int argc, char *argv[]) {
@autoreleasepool {
for (NSUInteger i=0; i<10000; ++i) {
// 要了 1KiB 的記憶體當 buffer
NSMutableData *buffer = [[NSMutableData alloc] initWithLength:1024];
// 做些事 ...
[buffer release];
} // for-loop 執行期間, 最尖峰的記憶體用量約 1KiB 多, 因為每個 Iteration 都有把 buffer 記憶體收掉
// -------------------------------------------------------------------------------------------------------------
for (NSUInteger i=0; i<10000; ++i) {
@autoreleasepool {
// 要了 1KiB 的記憶體當 buffer
NSMutableData *buffer = [[NSMutableData alloc] initWithLength:1024];
// 做些事 ...
[buffer release];
}
} // for-loop 執行期間, 最尖峰的記憶體用量約 1KiB 多, 因為每個 Iteration 都有把 buffer 記憶體收掉
// 但加上 auto release pool 沒啥幫助, 因為根本沒 call `autorelease`, 你都手動 release 掉了
// -------------------------------------------------------------------------------------------------------------
for (NSUInteger i=0; i<10000; ++i) {
@autoreleasepool {
// 要了 1KiB 的記憶體當 buffer
NSMutableData *buffer = [[[NSMutableData alloc] initWithLength:1024] autorelease];
// 做些事 ...
}
} // for-loop 執行期間, 最尖峰的記憶體用量約 1KiB 多, 因為每個 Iteration 都有把 buffer 記憶體收掉
// 因為這邊有 call `autorelease`, 所以 buffer 會放到最近的 auto release pool, 也就是 for loop 裡面的
// 所以 for loop 每回合的結束, 東西都有清掉
// 加上 auto release pool 很有幫助, 因為每個Iteration完, 都有清掉東西.
// -------------------------------------------------------------------------------------------------------------
for (NSUInteger i=0; i<10000; ++i) {
@autoreleasepool {
// 要了 1KiB 的記憶體當 buffer
NSMutableData *buffer = [NSMutableData dataWithLength:1024];
// 做些事 ...
}
} // for-loop 執行期間, 最尖峰的記憶體用量約 1KiB 多, 因為每個 Iteration 都**有**把 buffer 記憶體收掉
// 因為這邊沒 alloc, 所以其實做出來的 buffer 會放到最近的 auto release pool, 也就是 for loop 裡面的
// 所以 for loop 每回合的結束, 東西都有清掉
// 加上 auto release pool 很有幫助, 因為每個Iteration完, 都有清掉東西.
// -------------------------------------------------------------------------------------------------------------
for (NSUInteger i=0; i<10000; ++i) {
// 要了 1KiB 的記憶體當 buffer
NSMutableData *buffer = [NSMutableData dataWithLength:1024];
// 做些事 ...
} // for-loop 執行期間, 最尖峰的記憶體用量約 10,000KiB 多, 因為每個 Iteration 都**沒**把 buffer 記憶體收掉
// 因為這邊沒 alloc, 所以其實做出來的 buffer 會放到最近的 auto release pool, 也就是 `main` function 本身的
// 可是他還沒結束, 所以一直積著.
// -------------------------------------------------------------------------------------------------------------
@autoreleasepool {
for (NSUInteger i=0; i<10000; ++i) {
// 要了 1KiB 的記憶體當 buffer
NSMutableData *buffer = [NSMutableData dataWithLength:1024];
// 做些事 ...
} // for-loop 執行期間, 最尖峰的記憶體用量約 10,000KiB 多, 因為每個 Iteration 都**沒**把 buffer 記憶體收掉
}
// 你一定搞錯了什麼, 根本加錯順序了
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment