Pointers, am I using them correctly? Objective-c/cocoa - objective-c

I have this in my #interface
struct track currentTrack;
struct track previousTrack;
int anInt;
Since these are not objects, I do not have to have them like int* anInt right?
And if setting non-object values like ints, boolean, etc, I do not have to release the old value right (assuming non-GC environment)?
The struct contains objects:
typedef struct track {
NSString* theId;
NSString* title;
} *track;
Am I doing that correctly?
Lastly, I access the struct like this:
[currentTrack.title ...];
currentTrack.theId = #"asdf"; //LINE 1
I'm also manually managing the memory (from a setter) for the struct like this:
[currentTrack.title autorelease];
currentTrack.title = [newTitle retain];
If I'm understanding the garbage collection correctly, I should be able to ditch that and just set it like LINE 1 (above)?
Also with garbage collection, I don't need a dealloc method right?
If I use garbage collection does this mean it only runs on OS 10.5+? And any other thing I should know before I switch to garbage collected code?
Sorry there are so many questions. Very new to objective-c and desktop programming.
Thanks

I have this in my #interface
struct track currentTrack;
struct track previousTrack;
int anInt;
Since these are not objects, I do not have to have them like int* anInt right?
That would declare a pointer to an int stored somewhere else.
And if setting non-object values like ints, boolean, etc, I do not have to release the old value right (assuming non-GC environment)?
release is a message. You can only send a message to a Cocoa (or, in some cases, Core Foundation) object.
The struct contains objects:
typedef struct track {
NSString* theId;
NSString* title;
More precisely, it contains pointers to objects.
You can't ever have an object stored directly in a variable; you can only allocate it dynamically by sending an alloc message to a class, and receive the pointer to the allocated instance. Similarly, you can only send a message to a pointer to an object; you cannot and should not dereference a pointer to an object.
For these reasons, we almost always elide the “a pointer to”. We speak of the pointers as if they are the objects, but, in precise truth, they are not.
} *track;
That's correct if you want to declare the track type as being a pointer to a struct track. Generally, this will confuse people.
Lastly, I access the struct like this:
[currentTrack.title ...];
currentTrack.theId = #"asdf"; //LINE 1
So the previous line is line 0? ;)
I'm also manually managing the memory (from a setter) for the struct like this:
[currentTrack.title autorelease];
currentTrack.title = [newTitle retain];
If I'm understanding the garbage collection correctly, I should be able to ditch that and just set it like LINE 1 (above)?
If you're using garbage collection, then the autorelease and retain messages will do nothing, so yes, the plain assignment and the assignment with (ineffectual) release and retain messages are equivalent.
I do question why you're putting this information in a structure and not a model object, though.
Also with garbage collection, I don't need a dealloc method right? If I use garbage collection does this mean it only runs on OS 10.5+? And any other thing I should know before I switch to garbage collected code?
Yes: Read the Garbage Collection Programming Guide. It tells you everything you need to know, including the answers to the previous two questions.
As for pointers, you may want to read my pointers tutorial. The title says C, but everything in C is also true in Objective-C.

Although you seem to understand this stuff all right in general, I'd strongly recommand against storing objects in a struct. Getting proper memory management for that will be very troublesome — because even though the struct itself doesn't require memory management, the objects still do, and unless the struct is only ever accessed through a function API (essentially making it s poor man's object), you're going to have a tough time ensuring that happens. Like Peter said, that makes sense to be a model object.

Correct, correct, no, yes, correct, yes, and Apple's Garbage Collection Programming Guide is a good read.

Related

If you bridge a CFArrayRef of CFStringRefs to NSArray, can you treat the contents as NSStrings?

Suppose I have a CFArrayRef containing CFStringRefs inside it and I bridge it over to NSArray using CFBridgingRelease(). Can I now treat the contents of the array as regular NSString instances and call all of the usual NSString methods?
If so, does this mean toll-free bridging happens recursively throughout the object when it's bridged? E.g. if I had a CFArray of CFArrays of CFDictionaries or something, they'd all be transparently converted to NSArray, NSDictionary, etc?
Toll free bridging does not involve any conversion (or there would be a cost), so talking about doing it recursively does not make sense.
What toll free bridging does in your case is determine who is responsible for managing the lifetime of the object - the programmer for the CF array, ARC for the NS array.
Further whether an object internally uses manual memory management or ARC is not important to the user of that object - they can use either style.
Combine the above and you have your answer: once you've handed your CF array of strings over to ARC your job is done.
HTH
CRD's answer is good and I've given it a +1. Here's a bit more explanation:
First, type-casting is a purely compile-time thing. And it doesn't cost anything. It just tells the compiler not to complain.
Toll-free casting of Core Foundation types to Cocoa types is because those objects are, under the hood, the same thing. The cast is just necessary to inform the compiler of that fact. Such a cast doesn't "do" anything. For example, in non-ARC code:
CFStringRef cfstring = /* ... */;
NSString* nsstring = (NSString*)cfstring;
That assignment is still just an assignment. The pointer value from cfstring is still just copied verbatim into the storage of nsstring. Nothing else happens.
Depending on how you obtained the CFString that cfstring was pointing to, you may have had a responsibility to release it. Since this is non-ARC, you still have that responsibility after it has been assigned to nsstring, which you can discharge either by calling CFRelease(cfstring) or [nsstring release] or [nsstring autorelease] when you're done with it. Once you do that, the value in both variables must be considered unusable as dangling pointers.
The case with ARC is only slightly different. An ARC bridging cast is also a compile-time thing, but it affects what code the compiler emits for automatic memory management. Since it has emitted different code, that technically has implications for run-time, but they are not related to the type-cast as such. The bridging cast tells the compiler whether it should emit retains or releases (or neither) of the object which is the subject of the expression. That's all; just a question of retaining or releasing the object. So, it has no effect on, say, objects within an array because those objects are not the subject of the expression, the array is. And it doesn't even do anything to the array beyond potentially retaining or releasing it.
Let me try and take a simpler approach to an answer:
A CFArrayRef can be treated as an NSArray* and vice versa.
A CFStringRef can be treated as an NSString* and vice versa.
Thus, an CFArray of CFStrings is an NSArray of NSStrings. You just need to cast it. (In so doing with __bridge_*, you also transfer the memory management to ARC.)

How to safely store an id object in a C++ void* member under ARC when no other references hold on to the object?

I'm working with Box2D (C++) and I create an Objective-C object and assign it to a Box2D body's userData property, which is of type void*.
Now in some cases the void* userData may be the only active reference to that ObjC object. Therefore, because I used (__bridge void*) in the assignment, ARC is letting it go. That's something I need to fix.
I've been pondering the options to prevent this from happening? I read Clang's ARC documentation, specifically the parts about bridge casting (as well as Q&A on SO) as well as nodding to the various bridge casting constructs they consider to be "ill-formed".
Still, my first thought was to use (__bridge_retained void*) in the initial assignment to userData. But that made me wonder how to balance that retain? I obviously can't send release to the object.
So would I have to CFRelease() the object? Or would it need to be CFBridgingRelease()? Or are both illegal here?
Is a (__bridge_transfer void*) cast from userData to a temporary id type enough, perhaps while setting userData to NULL afterwards? Is that even a good idea?
I know the alternative would be to keep a separate NSArray/NSDictionary for the userData objects and keep them in synch with the lifetime of the Box2D body, adding and removing them in synch with their Box2D bodies.
But this feels like overkill because here I know what I'm doing, I know I need to +1 the object for as long as the Box2D body is active, and -1 the object when the Box2D body is removed. Plus I know that there are only two methods where the Box2D bodies are being added and removed, and direct access to userData is not even possible in my framework because all Box2D objects are hidden behind Objective-C interfaces/wrappers.
Setting possibly "ill-formed" aside for a moment, what would you recommend I should do in this situation?
__bridge_retained means "Send this ARC object off into no-ARC land by retaining it". You call this when you need to create an "untracked" void *. So, in your case, userData = (__bridge_retained void *)obj.
__bridge_transfer means "Pull this object back from no-ARC land by releasing it". You call this when you want to effectively invalidate the void *. So, obj = (__bridge_transfer id)userData. After this, the userData pointer is not safe to use; instead, you work only with obj. When obj goes out of scope, ARC will release it for the last time. This may entail creating a temporary id solely for this purpose.
So, in your case, you do want to use __bridge_retained when you ship the object off into Box2D, and use __bridge_transfer when you want to invalidate the userData. If you need to access the userData as an Objective-C object but not invalidate the pointer, use plain __bridge.
You misunderstood what the author of the documentation was meaning for "ill-formed". This is ill-formed:
NSData* data; // Initialized
NSData* data2= (__bridge NSData*) data;
Also this is ill-formed:
void* data; // Initialized
void* data2= (__bridge void*) data;
This is not ill-formed:
NSData* data; // Initialized
void* data2= (__bridge void*) data;
To be not ill-formed is enough that the left value is retainable and the right value is not retainable, or viceversa. So since in your case your're casting object pointers to raw pointers and viceversa, your approach is correct.
At your place I'd implements a smart pointer that sends a CFBridgingRetain message on construction, and a CFBridgingRelease message on destruction.

Difference between an object and a pointer

as the title says, what is the difference between a pointer and an object.
Say I have this code..
NSString *red = [[NSString alloc]initWithFormat:#"%#"];
and this code..
NSString *blue = [NSString stringWithFormat:#"%#"];
Is it correct to assume that they're both pointers to an object and pretty much the same? And if so, how should I think of objects in my mind ?
I do apologize if the answer exists already, I did use the search function but I've only found examples of this in the C++ language and wanted to make sure how it was in objective-c.
In addition to Basile Starynkevitch and Bram's answer,
In objective C the difference between your code line is,
NSString *red = [[NSString alloc]initWithFormat:#"%#"];
**Above code says you own red object so it's your responsibility to release it.
NSString *blue = [NSString stringWithFormat:#"%#"];
**You don't own it someone else in your program deep down inside will own this and you don't have to release this.
I would suggest for more information reading Apple's documentation is GREAT! specially Learning, "Objective C programming guide"
Good luck!
PS : iOS 5 has new feature, memory management is done by iOS itself, Now developer can be more creative instead doing 3 grade mathematics of reference counting :)
Pointers are a C concept, and they're identical in C, C++, and Objective-C. They are simply an integer that holds the memory address where an object is stored. In your example, both of those messages dynamically create an NSString object. Where that object is stored in your application's memory is up to the OS to decide, and you really don't care. So the OS allocates some memory and stores an instance of NSString in it. It then gives you back a pointer to that object, which you can use to reference the actual object at a later time.
A pointer contains the address in memory where is stored the object.
Memory address Object
-------------- ---------
0
1
2
3
4
...
pointer ----> 10523 myObject1
10524
...
An object is an instance of a class. It takes up memory while and should be released when you are finished with it. The pointer is your reference to the object.
NSString *red = [[NSString alloc]initWithString:#"red"];
and this code..
NSString *blue = [NSString stringWithString:#"blue"];
red and blue are both pointers to different objects.
The importance difference here is that red is owned by you and blue is not
[[NSString alloc]initWithString:#"red"];z
returns an object that you own and have to release later
[NSString stringWithString:#"blue"];
returns an object that is not owned by you and will be released the next time the autorelease pool is emptied
These concepts are covered in The Objective-C Programming Language guide by apple (I pointed you to the specific section, its a huge document, but the section 'Objects, Classes, and Messaging' should be the most helpful to your questions)
i hope i can make this abit clearer.
the object is in memory. the pointer is like an arow to the memory where the object is.
see it like a directional sign to a building.. the building is the object, the directions are the pointers.
(I'm not an Objective C expert, but)
Think of objects as memory zones, a pointer refer to the zone but is not that zone.
Gross analogy: your car plate number is not your car. A number is a number (made of digits, or more abstractly an element of the set of naturals). A car is something you drive.
Also not an Objective-C expert. Here's my best guess.
Both of those types seem to be pointers. However, it looks like the difference is that the first (where you are using alloc) puts you in charge of the associated memory.
With the second type, if you instantiate the object, use it, whatever, and then it goes out of scope, the OS will likely clean it up for you. However, with the first type, you are in charge of releasing that allocated memory back to the OS.
I'm guessing that objective-C has some sort of reference counting and memory management built in to detect when that object is no longer being referenced anywhere, but the important part is that that object should persist beyond the scope of that declaration as long as you've still got a reference somewhere.
You can probably find a lot of information by reading this post: Objective-C pointers?
As far as the general definition of "object" and "pointer": Both of those types are pointers. One you are in charge the memory, and the other the OS takes responsibility for you. An object is simply defined as an instance of a class. A pointer is the memory address of that instance.

Why doesn't the Objective-c runtime set dealloc'd object instances to nil?

Sometimes I set objects to nil after releasing them to avoid crashes due to unexpected messages sent to dealloc'd objects.
Why doesn't the Objective-c runtime do this automatically when an object is finally dealloc'd?
Because pointers are passed by value and not reference. All dealloc gets is a local copy of the pointer; any changes it makes are discarded. Same goes for C's free and C++'s delete.
How would the runtime be able to track down all such references?
MyClass* a = [MyClass new];
MyClass* aCopy = a;
[a release];
a = nil; // Tidy up
[aCopy crashNowPlease];
Sometimes you can catch this sort of thing with Build & Analyze.
Also, you will be able to use zeroing weak references in the future (or, Mike Ash created such a facility).
In objective-C, the objects are always accessed as pointer.
Setting an object to nil simply change the pointer value, not the object value.
In your method, you have only access to the object's value, not to the pointer pointing to it!
As #David Dunham says, you can have more than one pointer to an object, so how would the compiler knows?
And more than that, to make things easier, imagine the following code :
int a;
int* aPtr = &a;
If you change a value, you can access the changed value via *aPtr right? But you can change a value as long as you want, it won't change aPtr value, as it is not the same variable!
Thus, even if you only have one pointer to your object, if you modify the object's value, you pointer will still point to the same address value!
What you are describing is called a zeroing weak reference. This feature is available in OS X 10.7's Automatic Reference Counting (ARC) runtime. Prior to 10.7, you can use Mike Ash's zeroing weak reference implementation.
Without explicit runtime support (and some small but unavoidable overhead), standard C-style pointers (id in Objective-C is a pointer to a structure) are just a memory address (an integer) and not tracked by the runtime. There's nothing stopping you from making copies of this value elsewhere in memory or from storing the value in an integer of the appropriate size and casting to an id later on (of course if you do any of this, you kill a baby seal). Thus, when an object is dealloc'd there's no way to know where (or how many) references there are to that object.

Can we release some memory in Objective-c that a variable does not own but points to?

I have some code like this:
NSObject *var1 = [[NSObject alloc] init];
NSObject *var2 = var1;
[var2 release];
var1 = nil;
Is this correct or is this a memory leak?
As far as I know only var1 can release the memory alloc-inited in the first line, as per the Object Ownership policy
Your code will release the memory, because there is a single alloc, and a single release - the amount of pointers to the object is not a factor.
Ownership is a concept that the Object Ownership policy talks about because if you follow the guidelines it makes it easier to manage and ultimately prevent problems relating to releasing things you shouldn't release (or not releasing things you should).
Your code is all right and doesn't leak. But it seems like you don’t really understand pointers. A pointer can not own another object, it is just a reference that tells the computer which object is being accessed. In the reference-counted memory model of Cocoa it doesn’t matter at all how many pointers point to a single object.
You really should learn C (especially about pointers) before you try to learn Objective-C.
Your example will not result in a memory leak as var1 and var2 point to the same object in memory—thus the alloc call has a matching release. If the NSObject was retained as it was assigned to var2 however, there would be a memory leak as there would be no matching release.
When the memory management guide talks about the concept of ownership, it doesn't mean that a variable (e.g. var1) owns an object; it's more about what "scope" owns it (e.g. a class or method). In your example, the method containing those statements would be responsible for releasing the object.
It's the object that keeps a reference count, not the pointer to the object. If you have a dozen pointers to an object, you could use any one of them to release the object because they're all pointing to the same object. However, it's a lot easier to follow your code and make sure that you don't have memory management problems if you don't play those sorts of games.