ios - Memory Growth Mystery (Objective-C) -
i have memory growth issue in app.
since describing full code here intimidating, narrowed down simple scenario switch , forth between 2 view controllers learn basic memory dynamics.
- (void)viewdidload { [super viewdidload]; (int i=0; i<100000; i++) { __weak nsstring* str = [nsstring stringwithformat:@"abcsdf"]; str = nil; } }
this supposed show no memory growth, because allocate 'str' , deallocate 'str' making 'str' becomes nil, losing owner.
but, memory keeps growing. everytime load view controller, memory keeps growing , never coming back.
can tell me why that? using arc.
your code snippet includes several interesting things ios/os x memory management.
__weak nsstring* str = [nsstring stringwithformat:@"abcsdf"]; str = nil;
the code same following without arc.
nsstring* str = [[[nsstring alloc] initwithformat:@"abcsdf"] autorelease]; str = nil;
because stringwithformat:
class method not begin "alloc", "new", "copy", or "mutablecopy". it's naming rule. nsstring object retained autorelease pool. autorelease pool might in main runloop. nsstring object not deallocated immediately. causes memory growth. @autoreleasepool
solves it.
@autoreleasepool { __weak nsstring* str = [nsstring stringwithformat:@"abcsdf"]; str = nil; }
the nsstring object deallocated @ end of @autoreleasepool
code block.
by way, [nsstring stringwithformat:@"abcsdf"]
might not allocate memory every time. reason it's static string. let's use class further explanation.
#import <foundation/foundation.h> @interface test : nsobject + (instancetype)test; @end @implementation test - (void)dealloc { nslog(@"test dealloc"); } + (instancetype)test { return [[test alloc] init]; } @end
here test code __weak
.
@autoreleasepool { nslog(@"begin: = [test test]\n"); __weak test *a = [test test]; nslog(@"end: = [test test]\n"); = nil; nslog(@"done: = nil\n"); }
the result of code.
begin: = [test test] end: = [test test] done: = nil test dealloc
you said deallocate 'str' making 'str' becomes nil, losing owner
. not correct. a
weak variable doesn't have ownership of object. autorelease pool have ownership of object. that's why object deallocated @ end of @autoreleasepool
code block. take @ other test code case.
nslog(@"begin: = [[test alloc] init]\n"); __weak test *a = [[test alloc] init]; nslog(@"end: = [[test alloc] init]\n"); = nil; nslog(@"done: = nil\n");
you can see compilation warning code.
warning: assigning retained object weak variable; object released after assignment [-warc-unsafe-retained-assign] __weak test *a = [[test alloc] init]; ^ ~~~~~~~~~~~~~~~~~~~
[[test alloc] init]
doesn't register object autorelease pool. well, no need @autoreleasepool
more. , a
__weak
variable, object not retained anything. result is
begin: = [[test alloc] init] test dealloc end: = [[test alloc] init] done: = nil
no ownership no life. object deallocated after allocated. think wanted write code without __weak
following.
nslog(@"begin: = [[test alloc] init]\n"); test *a = [[test alloc] init]; nslog(@"end: = [[test alloc] init]\n"); = nil; nslog(@"done: = nil\n");
the result expected. object released assigning nil
strong variable a
. no 1 has ownership of object, object deallocated.
begin: = [[test alloc] init] end: = [[test alloc] init] test dealloc done: = nil
Comments
Post a Comment