Last active
October 12, 2016 23:44
-
-
Save sodastsai/a071e3b961000a3148eb5ecae4a0558b to your computer and use it in GitHub Desktop.
Auto release pool
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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 已經結束囉 | |
--- | |
*/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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