I have an object that has several properties. If I have a pointer to one of those properties, is it possible to get a pointer to the class instance to which that ivar belongs?
for example: foo.bar, where I know the address of bar, can the address of foo be found?
This seems related to: run time references but I didn't see any references that were quite what I'm looking for.
Thanks for your help!
First, you need to adjust your terminology a bit. You cannot have a pointer to a property, because a property is an interface to an object, specifying the format of the getter and setter methods.
If you had a pointer to the getter, a method (IMP) at best you could get back would be a pointer to the class, certainly you could not get back to an instance.
If you had a pointer to an ivar, I don't believe there is any way to get back to the containing object instance. If you had an array of all posible foos, it might be possible to ask each of them for a list of ivars, and get the address of each ivar and eventuallty find the instance in question that way.
The best solution is for bar to contain a parent reference to foo, so that foo.bar.foo will give you the answer you want. But it depends on what exactly you are trying to do. The normal Cocoa way for a lot of these things is to pass foo as well, as is done for many delegates. For example:
[obj foo:foo doSomethingWithBar:foo.bar];
Unless the object has a pointer back to it's "parent" or you explicitly track it yourself, I don't believe there's a way to resolve that. You'd really have to trace through memory to find what basically amounts to "who points to me". It's essentially the same problem as finding the previous node in a singly-linked list — you have to start from the beginning and stop when you reach the node that points to the node of interest.
The problem with trying to track down foo from the address to bar is that foo.bar is a pointer that contains the address of an object, and only foo calls it "bar". For simplicity's sake, imagine that foo is at address 0x1000, and foo.bar is at 0x1008 and points to another object at 0x2000. Now, if you have the address 0x2000, there's no easy way to know that 0x1008 points to it.
It's even more complicated if you imagine that N other addresses might also point to 0x2000, so even if you did scan memory, you wouldn't know whether the pointer belonged to an object, struct, local variable, or even was just a random pattern that happened to match the address you're looking for.
You could do it if you have a pointer to the instance variable itself, rather than the contents of the instance variable.
Foo * reference = [[Foo alloc] init];
Foo * foo == [[Foo alloc] init];
int * barptr = &(foo->bar);
Foo * baz = (Foo *)((char *)barptr - ((char *)(&(reference->baz)) - (char *)reference));
Related
Hi I know that when accessing members in C using the arrow notation (->) makes elminates the need for using both star and dot (* .) every time an object needs to be accessed.
But in Objective-C is there any difference between self.myivar and self->myivar? I have noticed that both of them work in my case, where I have an myivar declared as a property.
But in Objective-C is there any difference between self.myivar and self->myivar?
Yes, there's a difference. Assuming that foo is a pointer to an object:
foo->bar is equivalent to (*foo).bar where the dot indicates the member access operator to get the instance variable bar.
foo.bar is equivalent to [foo bar]; that is, it sends the message -bar to the object pointed to by foo. That may just return whatever is in foo's bar instance variable, but it may do other things. There may not even be an instance variable named bar. As long as there's a method called -bar, however, foo.bar is valid. There should also be a -setBar: method if you're using foo.bar as the left hand side of an assignment, like: foo.bar = baz;.
Note that although self is a keyword in Objective-C, it always acts as a pointer to an object. There's nothing special about self with respect to accessing properties or instance variables. I've used foo as the name of the object pointer above to demonstrate that property/ivar access works the same way for any object pointer, but you could substitute self for foo above.
I am having problem with understanding one concept of memory managment, because I am new to objective C. For instance lets say I have a class Bar and Foo.
in main function I call:
Foo *foo = [bar getFoo]; //In my bar method I return foo
[foo retain];
[foo callMethod];
[foo release];
I know this is right way to do it. But why do we have to retain it after we get it from another object, does not this mean returning object has retain count 0 ? so we have to reatin it to count 1 to use it? but if it has reatin count 0, how do we know it is still there. We can assume since it is the next line that increment retain count that the object memory wont be realocated, but what if we have multi-threading program?
When an class method returns an object, it will autorelease it so you don't have to bother; typically:
- (Foo *)getFoo
{
return [[_foo retain] autorelease];
}
If you are only using foo for the lifetime of the calling method you don't need to retain it, as it won't be autoreleased until next time through the run loop, so your code should actually be:
Foo *foo = [bar getFoo]; //In my bar method I return foo
[foo callMethod];
If, however, you want to hold foo for a while, outside the scope of the calling method, you need to retain it and then release it sometime later.
One more thing; the convention for getter method names is simply "name", so your setter should be setFoo and your getter would be foo. Keeping to the naming conventions is a good idea as it lets you know what a method does, in say 7 months time, and tools like static analysis understand the conventions.
The method getFoo doesn't return an object with a 0 retain count. It returns an object with a +0 retain count which means that:
the object's retain count is not null (otherwise, the object wouldn't exist)
and the retain count wasn't altered by the invocation of the method, or if it was, it was in a balanced way (with as many release/autorelease as retain/alloc/new/copy).
Thus the lifetime of the object entirely depends on where and how it is retained. We don't know how long the object will be valid as any method invocation could release the object.
For example, let's consider the following code:
id anObject = [anArray objectAtIndex:0];
[anArray removeObjectAtIndex:0];
The object anObject isn't retained any more by the array as we removed it. Therefore it may have been destructed (but maybe it wasn't because it is still used somewhere else).
Generally, when getting an object from a method (other that alloc, copy, new or retain), we can assume that:
either the object was retained then autoreleased,
either the object is retained by the object that returned it.
So we know the object foo is valid until we return from the current method/function or we invoke a method/function that alter the state of the object bar, whichever comes first. After that, it may have been destructed.
So in your case, you can safely omit the retain/release pair.
However, it is very difficult to guaranty that an object doesn't get released unless we know the implementation of every method we invoke. Therefore, retaining (then releasing) every single object we get is the safer approach and that's what the compiler will do when you enable ARC (Automatic Reference Counting).
But that would require you to write a lot of retain/release and your code would become difficult to read, understand and maintain. Moreover, the more code you write, the more bugs you get (unless you never write bugs).
In conclusion, you don't need to retain an object unless you have a reason to suspect it could vanish otherwise.
Is this pointer assignment correct?
customclass.somearray = &*otherarray;
where somearray and otherarray are NSArray objects.
If not, how do I solve my problem:
I want to share this otherarray object with customclass.somearray. And I want all changes
made to customclass.somearray to be made to the original otherarray too.
Doing it this way, it works. I just want to ask, is it correct?
Your two variables are pointers of the same type, so just assign one to the other:
customclass.somearray = otherarray;
The way you have written this is unnecessary. Using the dereference operator * essentially gives you the "contents" of the pointer. The address-of operator & correspondingly gives you the address of whatever you apply it to. Your pointer otherarray contains an address. If you dereference that address and then take the address of that, you end up right back where you started.
Be aware that the left side of this assignment is a property access (assuming that customclass is also an object and not just a struct). This means that the compiler will change your expression into:
[customclass setSomearray:&*otherarray];
// And my version will be changed into:
[customclass setSomearray:otherarray];
That is, it becomes a method call rather than a simple assignment. This does not affect the syntax you should use, however.
When working in Objective-C, you never deal with objects directly, but always refer to them via pointers. Always. In C++, you can declare an actual object on the stack, for example, but you never do that in Objective-C. So, if you have:
NSArray *otherArray = [NSArray arrayWithObjects:#"foo", #"bar", nil];
then otherArray is a pointer to an instance of NSArray. Likewise, your somearray property will be of type NSArray*, so the types will match and you can just assign one to the other:
customclass.somearray = otherarray;
Hope that helps.
being a Cocoa/Obj-C newbie I am going through the "Cocoa Programming for Mac OS X" book by Aaron Hillegass and - leaving apart the fact that now we have also the chance to use GC to avoid all this reasoning - I am not sure I get the reason for some of those retains.
In particular in one of the examples Aaron gives as good programming practice:
- (void) setFoo:(NSCalendarDate *)x
{
[x retain];
[foo release];
foo = x;
}
I don't get the reason for retaining the x instance at the first line of the method:
[x retain];
The scope of this instance is just the set method, right?
When exiting the method scope the x instance should be deallocated anyway no?
Besides, when assigning x to foo with:
foo = x;
foo will be anyway pointing to x memory cells and will therefore increment the pointed object retain count, no? This should ensure the memory won't be deallocated.
So, what's the point? I am sure I am missing something, of course, but don't know what exactly.
Thanks,
Fabrizio
Retain means: I will be needing this object to stay around, it must not be deallocated. If x wouldn't be retained, the following is likely to happen:
You assign x to foo, so foo now points to the address where your NSCalendarDate is. Someone releases or autoreleases this object, it's retain count eventually drops to 0 and the object is deallocated. Now your foo still points to that address, but there's no longer a valid object. Sometime later, a new object is created and by chance it's situated at the same address than your old NSCalendarDate object. Now your foo points to an entirely different object !
To prevent that, you need to retain it. You need to say, please do not deallocate the object yet, I need it. Once you're done with it, you release it which means I no longer need the object, you can clean it up now if nobody else needs it.
Now for the classical three part assignment. Consider your setFoo: would look like this:
- (void) setFoo:(NSCalendarDate *)x
{
[foo release];
[x retain];
foo = x;
}
This is a very bad idea. Consider your object is the only one who has retained the NSCalendarDate object, and consider you would then do: [self setFoo:foo];. Might sound silly, but something like this can happen. The flow would now be this:
foo would be released. Its retain count might now drop to 0 and the object will get deallocated.
Whoops, we're trying to retain and access a deallocated object.
This is why you always first retain the new object, then release the old object.
If you're coming from a Java or .NET background, it is very important to understand that a variable of type Foo * only contains the address of your object, nothing more. In Java or .NET, a variable that points to an object automatically "retains" it, if you will. Not so in Objective-C (in non-GC environments). You could consider a variable of type Foo * to be a weak reference, and you explicitly need to tell Objective-C whether you will still need that object at that address or not.
I'll cut a really long story short and give an example of my problem.
Given a class that has a pointer to a primitive type as a property:
#interface ClassOne : NSObject
{
int* aNumber
}
#property int* aNumber;
The class is instantiated, and aNumber is allocated and assigned a value, accordingly:
ClassOne* bob = [[ClassOne alloc] init];
bob.aNumber = malloc(sizeof(int));
*bob.aNumber = 5;
It is then passed, by reference, to assign the aNumber value of a seperate instance of this type of class, accordingly:
ClassOne* fred = [[ClassOne alloc] init];
fred.aNumber = bob.aNumber;
Fred's aNumber pointer is then freed, reallocated, and assigned a new value, for example 7.
Now, the problem I'm having;
Since Fred has been assigned the same pointer that Bob had, I would expect that Bob's aNumber will now have a value of 7. It doesn't, because for some reason it's pointer was freed, but not reassigned (it is still pointing to the same address it was first allocated which is now freed).
Fred's pointer, however, has the allocated value 7 in a different memory location.
Why is it behaving like this? What am I minsunderstanding? How can I make it work like C++ does?
Edit:
Right, a fresh morning and I can see I gave a really bad, 5pm syndrome example.
What I'm trying to do is more like this:
#interface classOne : NSObject
{
int* numA;
}
#property int* numA;
#implementation...etc
numA is alloced and assigned a value. Later on, in a seperate thread (with necessary locks etc), this is done:
int* numB= malloc(sizeof(int));
*numB = 5;
free(RefToClassOne.numA);
RefToClassOne.numA = numB;
numA does get freed, but does not get assigned the value that numB is pointing to, which is the behaviour I would like.
Part of the longer story is that it is the vertex count for part of a vertex buffer that is passed into openGL. I realise that it shouldn't be a pointer, but the float* buffer for the coordinates is dealt with in the same way and needs to be of variable size, so I want to fix this to solve that problem also.
What you are misunderstanding is that (a) you cannot pass things by reference in Objective-C, and (b) even if you could, it wouldn't help you here.
Objective-C only allows you to pass things by value. Sometimes, as in the case of objects or pointers, the value you are passing is itself a reference, but it's being treated as a value. C++-style transparent references don't exist.
But suppose that we had them. How would that help in this case? The aNumber instance variable is still of type int*; when you assign to it (as in fred.aNumber = bob.aNumber), you must create a copy. At this point, it doesn't matter what was passed by reference, and nor does it matter that things are instance variables. Your code is effectively the same as
int* bobNumber;
int* fredNumber;
bobNumber = malloc(sizeof(int));
*bobNumber = 5;
fredNumber = bobNumber;
Here, bobNumber and fredNumber are different variables—they have different names, live at different locations in memory, etc.—that happen to have the same value. Now, the value they have is a reference to another location in memory, so they are equivalent references. However, what happens if we change one of them?
free(fredNumber);
fredNumber = malloc(sizeof(int));
*fredNumber = 7;
Since function arguments are passed by value, free can't do anything to fredNumber itself; it can only operate on fredNumber's value, freeing the referenced memory. Since this is the same as bobNumber's value, we see this effect if we try to dereference bobNumber. Next, we assign a value to fredNumber. Since fredNumber and bobNumber live at different locations in memory, this assignment naturally does nothing to bobNumber. At this point, fredNumber != bobNumber, so naturally when we assign 7 to *fredNumber, nothing happens to *bobNumber (which is invalid anyway, having just been freed).
Note that your comment about "making it work like C++ does" is strange; C++, like I said, doesn't work this way either. If you really wanted to make this work in C++, you would have to have a reference instance variable
class ClassTwo {
public:
int*& aNumber;
ClassTwo(int*& an) : aNumber(an) { }
};
Note that an needs to be passed by reference; I originally tried to do it without that, and then a copy was created in the constructor, producing the same old set of problems.
Now, whether or not we pass bob by reference, it will still have the same aNumber reference, so we can construct something like
int* shared;
ClassTwo bob(shared);
bob.aNumber = new int(5);
ClassTwo fred(bob.aNumber);
delete fred.aNumber;
fred.aNumber = new int(7);
And everything will work like you expect. However, this may well not be a good idea. For one reason why, note the shared variable—references need to be able to reference something. And this can produce problems: if the object being reference goes out of scope, the behavior of the reference is undefined.
If you set both to point to the same object then when you free the object you are effectively removing what both are pointing to so both pointers become invalid. In order to reassign you need to repeat the same procedure by setting both pointers to point to the same new object.
Destroying an object will not automatically update all pointers that point to it since the pointers are independent from each other and don't know anything about each other.
You are better off by creating a clone from the original instead of sharing the object in question so that each 'aNumber' points to its own copy.
I guess what you are after is like in C++ you write
fred = bob;
where fred creates a copy of bob
in that case you would need some kind of clone function in your class.
EDIT: rephrased
Well, as far as I can see your code is doing exactly what you are telling it to.
Using a pointer to an int isn't the most compatible way of handling a value; you will need to call free on it appropriately, and it would strike me as far simpler to use a NSValue object if you just want to pass the value between objects.
This works the same way in C++. Here's an equivalent example:
class Bob {
public:
int *aNumber;
};
void wontWork() {
Bob bob, fred;
bob.aNumber = new int;
*bob.aNumber = 5;
fred.aNumber = bob.aNumber;
delete fred.aNumber;
fred.aNumber = new int;
*fred.aNumber = 7;
cout << *bob.aNumber << *fred.aNumber << endl;
}
Do you expect *bob.aNumber to be 7 here? When you did delete fred.aNumber, that freed the memory that both bob and fred pointed to. Then you reassigned fred to point to new memory, but you did not reassign bob, so it's just a dangling pointer. So there's nothing that would cause bob to be 7. Remember, pointers are just plain value types like ints. There's no magic that causes two pointers pointing to the same address to sync up with each other.