Skip to content

Fix memory leak which keeps strong reference to every target appearance methods are performed on#4

Open
carllindberg wants to merge 1 commit intoCollect3:masterfrom
carllindberg:FixInvokeTargetMemoryLeak
Open

Fix memory leak which keeps strong reference to every target appearance methods are performed on#4
carllindberg wants to merge 1 commit intoCollect3:masterfrom
carllindberg:FixInvokeTargetMemoryLeak

Conversation

@carllindberg
Copy link

NSInvocation appears to add all retained arguments (which includes the target) into an internal NSArray when retainArguments is turned on, and never removes them. This array is only freed up when the invocation itself is dealloced. Because CTAppearance by necessity has its stored invocations retain their arguments, every target the calls were invoked on got added to these arrays, and were never freed. They will not show up in Leaks because there are valid pointers to them.

My fix is to only turn on retainArguments if any of the arguments are in fact objects, since we never care about retaining the targets (and I don't think we care about retaining the return values, so I didn't check for that). Most setter methods of scalar values will fall into this category, so it seems worth it to check. When invoking, if the NSInvocation does not retain arguments, we can call invokeWithTarget: directly. Otherwise, we have to make a new NSInvocation instance as a copy, and call invokeWithTarget on the copy instead, to avoid the target from being retained, or if it is retained, then the copy will be dealloced right away and the strong reference will be released.

…e target) into

an internal NSArray when retainArguments is turned on, and never removes them. This
array is only freed up when the invocation itself is dealloced.  Because CTAppearance
by necessity has its stored invocations retain their arguments, every object the
calls were invoked with got added to these arrays, and were never freed.  They will
not show up in Leaks because there are valid pointers to them.

My fix is to only turn on retainArguments if any of the arguments are in fact objects,
since we never care about retaining the targets (and I don't *think* we care about
retaining the return values, so I didn't check for that). Most setter methods of
scalar values will fall into this category, so it seems worth it to check.  When
invoking, if the NSInvocation does not retain arguments, we can call invokeWithTarget:
directly.  Otherwise, we have to make a new NSInvocation instance as a copy, and
call invokeWithTarget on the copy instead, to avoid the target from being retained.
@sanekgusev
Copy link

Truly marvellous. Mind if I adopt this this to my https://github.com/sanekgusev/SGVAppearanceProxy?

@carllindberg
Copy link
Author

Sure, go right ahead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Comments