how to properly alloc/dealloc this pointer? objective-c - objective-c

*beginner iOS programmer, please explain with patience
suppose i have 2 classes - Foo, Bar
in class Bar, i have a pointer to an instance of Foo, which i set during init. (and because i dont know how to properly import Foo and Bar with each other, i end up setting the type to id instead of Foo)
#implementation Bar{
id pointerToInstanceOfFoo;
}
how do i write my dealloc function for Bar? or DO I even override the dealloc function?
right now i have
-(void)dealloc{
pointerToInstanceOfFoo = NULL;
[super dealloc];
}
i still want that pointer to Foo to be around when Bar dies, but am i doing things right? several questions:
if Foo and Bar imports from each other, how do i do this? or is this bad software design?
right now i have the pointer "pointerToInstanceOfFoo" set in the #implementation... is this equivalent to declaring a private pointer in class Bar?
should i instead be using
#property (nonatomic, weak) id pointerToInstanceOfFoo
instead? if so, why do i keep getting this error about no weak pointers in ARC?
do i need
delete pointerToInstanceOfFoo;
in the dealloc function??
Sorry for the confusion, any explanations/answers would be greatly appreciated!!
P.S. i'm using XCode 4.4 and running on iOS 5.0 with cocos2d v2.1 beta... i think it's using arc

You are not allowed to use [super dealloc] in ARC. So if that compiles, you are not using ARC and you need cals to retain and release. Writing a whole tutorial on that is not something that will fit in a stack overflow answer. As for your other questions:
1) Just import them in the implementation file, not the header file.
2) Yes
3) If it makes you happy. The error probably means you are targeting below iOS 5.0 (I.e. the deployment target in your project settings is set to less than 5.0), in which weak pointers are not supported, or ARC is turned off. I don't think you've accurately reported the error message since it makes no sense.
4) "delete" is not valid objective-c or valid c.
P.S. No, you don't want that pointer to be around after Bar is deallocated because that would be a memory leak. Perhaps you want a static variable instead of an instance variable?

As borrden mentioned, retain/release and objective-c memory management is a considerably large topic, one that has been extensively dealt with. I'd recommend reading this to get started and do some more research from there.
Though you can (should?) use ARC and save yourself some hassle, understanding the regular retain/release cycles will give you a better understanding of strong/weak references in ARC. While you don't have to understand everything about memory management in objective-c while using ARC, you still need to understand some of it.

Related

Objective-C init quirks

In a class interface I define some ivar
#property (strong,nonatomic) id < Protocol > initEst; // Initial estimate
This compiles without a problem but when I run the program it crashes with EXC_BAD_ACCESS and [Object .cxx_destruct] indicated by the debugger as the reason.
What is going on?
It's all about the rules of ARC automatic memory management. An initializer has special rules for how it treats the returned value: it retains and returns. See https://clang.llvm.org/docs/AutomaticReferenceCounting.html#semantics-of-init.
Objective-C in general, and ARC in particular, have some pretty strict rules about what names of methods mean. initXXX means "this is an initializer". If this isn't an initializer, don't use the init prefix.
You could turn off ARC entirely and manage memory yourself, but it's easier just to obey the conventions, and it fits better in case of interaction with other languages (such as Swift).
I have tested this some more and there seems to be three conditions for this particular quirk to show up.
In my particular case the ivar's Protocol was also the same as that of the containing class. This seems to be an additional requirement for this problem to surface (refering here to my earlier answer that did not mention this).
So to elaborate on my earlier answer. If
initXXX is an ivar
of id type
that implements a Protocol that is the same as the containing class
then the Objective-C + ARC compiler will happily compile the code but be unable to execute it.
Here is a sample of the code I used to test
#interface Dog : NSObject < Animal >
#property (nonatomic,strong) id < Animal > initState;
#end
Something like this will cause problems simply because the name starts with init. Change the name and all problems disappear.
For reference, the runtime error this generates is
Dog object overreleased while already deallocating
This snippet is pretty abstract but this may bite you in places where you need to specify some initial condition and where it is natural to name some ivar initXxx but beware, if you use Objective-C you do not have that luxury nor will the compiler warn you that it is wrong.
The original error seemed memory allocation related and caused me to suspect the way I used the autoreleasepool but now I am fairly convinced this has nothing to do with the issue.

Objective C: How to generate warning for instance variables not declared in the class’ interface?

I handled several issues recently when working on my company's iOS project using XCode 4.2 and Apple LLVM complier 3.0 / LLVM-GCC.
Below is the code
A.h
#interface A{
int _count;
};
#property(nonatomic,assign) count;
#end
A.mm
#implementation A
#synthesize count = _cont;//note a typo here !!!
//... I use _count in below code
#end
The typo will not generate a compile error or warning, the compiler or run-time (actually I am not sure who did it, to my best guess should be the compiler) will generate a _cont instance ivar for us.
This feature is great for encapsulation. Our header files could be much cleaner. However such a typo is hard to notice. So I am wondering if are there any setting to generate warning for this case? I search Clang's official site without any finding.
Someone would suggest me to not declare the instance in class interface at all and always use self.count. first I don't like this code style, second there are cases your "setCount" method may do something more than just change the instance value,lastly we began our product before this feature is introduced. I don't want to change exist code's style.
Does anyone here encounter the same problem? Are there any good ideas and best practice ?
This is not possible. How should the compiler recognize your typo?
Also you should have recognized that it is not necessary to write your own ivar for your property anymore, as #synthesize count = _count; is already enough to reach you iVar via _count later in the code.

ARC reference counting dealloc, and release

I am getting a bit confused. I am creating an app with storyboard, and running it on iPad 1. the application uses a lot of memory, so reached the 120mb, crashes. accordingly to what I have understood to remove this problem you need to release, dealloc... the point is that with ARC this should be automatic. In fact if I add for e.g.: [label1 release]; it gives me an error. But this ARC automatic release and dealloc does not seem to work! Is this because there are different ways to release with ARC??
You don't need to manually retain/release/autorelease with ARC. However if you have active references to a lot of unused objects they will still remain in memory. Profile your app with Instruments and it will show you how many objects you're creating of each class and how much memory they're consuming.
With ARC you still need to think about memory usage you just don't need to worry as much about memory leaks.
NSObject *bigMemObj = [[BigMemClass alloc] init];
//This creates the object in memory. In both arc and manual counting the retain count is 1
//Do stuff
//Prior to ARC you would have had to call [bigMemObj release]; before setting the variable to nil
bigMemObj = nil
//With ARC you don't have to do anything. The compiler inserts the release at compile time
Also read the documentation on declaring iVars __strong vs __weak.
Without looking at your code it's hard to identify what is consuming all the memory but hopefully that should help you determine where to start looking.
You should implement #autoreleasePool{} inside each method. In essence, each method will look like the following:
-(void)methodName{
#autoreleasePool{
//do method stuff
}
}
This will ensure that, upon exiting the autoreleasePool, memory is properly released.
I can't vote this back up, otherwise I would. I think Alessandro is asking about ARC vs using release and dealloc, not about what he's loading!
So, Alessandro, your understanding is correct that with ARC you don't release or dealloc. Therefore, those won't work if you're using ARC. Also, there is no alternative to release/dealloc, since ARC doesn't use it.
My suggestion would be to look at what you're using in the app that is taking up all this memory. Do you have a large number of pictures, for example, that are very large? Keep any graphics as small as possible, matching the resolution of the iPad. Especially the iPad 1, which doesn't have the "retina display".
You can use Autorelease pools in ARC. Here is some documentation on when to use them:
NSAutoreleasePool Class Reference
Advanced Memory Management Programming Guide: About Memory Management

Is it possible to have a memory leak under ARC by passing a block as an argument and then copying it? If so, how to prevent it?

I'm working on a Objective-C project and we have ARC enabled. I'm currently dealing with two separate classes, let's call them A and B.
A has a strong reference to B and B has a block property with the copy attribute.
#interface A {
B *b;
...
}
#end
#interface B {
...
}
#property (copy) void (^myBlock)();
#end
Now, if inside a method owned by A I try to assign to myBlock:
b.myBlock = ^{ [self doSomething] };
The compiler (correctly) complains:
Capturing 'self' strongly in this block is likely to lead to a retain cycle.
I understand this behaviour and how to work around it, based on the answers to this question. (Basically, a cycle is formed because once the block is copied it will contain a strong reference to A, which has a strong reference to B, which in turn has a strong reference to the block itself.)
Now, if instead of directly assigning the block to the property I pass it to a method of B:
[b takeMyBlock:^{ [self doSomething] }];
And inside that method I do the assignment, the compiler will no longer complain.
My question is: Will that create a memory leak? If so, how to avoid it? Is it possible to annotate the method argument somehow so that the compiler knows the argument is going to be copied?
Thanks in advance.
I just encountered the same issue myself. While the issue didn't manifest itself as a leak per se, I actually found the problem while analysing heap growth using the Allocations tool in Instruments -- so it obviously does cause a memory issue.
I think the compiler would have to be pretty smart to pick up on the problem and issue a warning, so my guess is that one of two approaches is needed:
Documentation: As you suggested in your question, clearly document
that this method will copy the block passed to it. This might
involve naming the block parameter something like blockToCopy
(Xcode helpfully displays the block parameter name when using
autocompletion). Also, comment the method declaration. If you're
using a documentation tool like appledoc this is particularly nice,
as your documentation will also appear in Xcode's quick help dialog
when option clicking your code.
Never capture self strongly in a block: This is perhaps best
practise, as I don't think it's ever a good idea to keep a strong
reference to self inside a block. If you have to reference self,
use a weak reference. This will certainly avoid the situation you
describe. (N.B. referencing an instance variable will also keep a strong
reference to self).
In ARC, what it does is if a local variable or a WEAK variable loses it reference. The memory will be dealloced immediately since its reference count is zero. However, if you are reallocating a STRONG variable, it will definitely cause a memory leak for strong variable retains even if reference count decays to zero. In this case, you shall set this variable to NIL before reallocation or set the variable to weak if strong property is unnecessary.

How to prevent automatic retain/release when calling Obj-C message from C++?

I've got some code like this:
#interface MyTimer : NSObject
- (int)getValue;
#end
#interface TimerHolder : NSObject {
ExternalControl* m_externalControl;
}
#property (retain, nonatomic) MyTimer* timer;
#end
class ExternalControl {
__unsafe_unretained TimerHolder* m_holder;
public:
ExternalControl(TimerHolder* holder) : m_holder(holder);
int getTimer() { return [m_holder.timer getValue] };
};
The method ExternalControl::getTimer() is called very frequently. During profiling, I noticed that during a call to getTimer(), obc-j also calls objc_retain and objc_release (presumably on m_holder or m_holder.timer), which ends up sucking up a lot of time! Removing __unsafe_unretained didn't make a difference.
By construction, I know that whenever ExternalControl::getTimer() is called, m_holder and its timer will stay alive for the duration of the call, so I think the retains/releases are unnecessary.
Is there any way to prevent them from being called?
I'm using XCode 4.2 with iOS 5 SDK, with ARC enabled. Is ARC responsible and removing it would remove the retains/releases? (I didn't want to spend time re-creating a project without ARC just to test this, before checking with you my friends!)
I can only speak from a non-ARC experience as I haven't used it yet (and not planning it being old school).
However, I have several projects using a C++ library and keeping references to it in the obj-C code.
I know for a fact that retain/release isn't called unless explicitly requested.
BTW, I couldn't use Obj-C when linking the C++ library and instead had to use Obj-C++ otherwise the C++ constructor/destructors weren't called as expected. It was just a matter of renaming the .m file into .mm
Hope this help.
If you want to manually handle retain/release for just that class (disable ARC).
set the "-fno-objc-arc" compiler flag in the build phases tab for that source file.
The WWDC 2011 sessions on ARC specifically mention that when compiled for debug, ARC retain/releases are not optimized.
If you haven't, try running your code in Release mode and profiling it. You should see a significant difference.
However, I know ARC doesn't take into account the kind of design assumptions you imply when you say "By construction". But, ARC shouldn't be touching your your "__unsafe_unretained" instance variable... are you sure those retain/release calls are being passed a pointer to that?