On 6 Mar 2009, at 09:15, Xavier Glattard wrote:
Richard Frith-Macdonald a écrit :
On 6 Mar 2009, at 07:05, Xavier Glattard wrote:
Hi
I dont understand this problem about ABI and binary compatibility,
so
please excuse me if this looks stupid :\
The problem comes from ivars that would not be always at the same
offset, doesn't it ? But these ivars are supposed to be private,
dont
they ? So the code that uses these ivars is always released along
with
the class interface. I can not find any official 'public' ivars.
Do i
miss something ?
There are all sorts of possible issues with symbol names when
functions and global variables etc are added/removed/changed, but
the main issue we are talking about is the ivar layout and
subclassing.
If you add an ivar to a class, the memory used by and instance
becomes bigger to make room for it.
If you link in some bundle or library which uses a subclass of that
class, the bundle/library will not be expecting that ivar to be
there, and will have stored one of the subclass ivars at the
oiffset in memory where the new ivar is stored ... causing obvious
problems.
David's solution of non-fragile ivars requires compiler and runtime
support, but is definitely the way to go to solve the problem
(except for when the very highest performance is needed, in which
case you can usually use straight C and other techniques for
optimisation).
Fred, Richard : thank you for your answers.
I think I understand the 'technical' problem :)
But IMHO :
- private ivars should (can?) not be used from outside the class
itself.
- protected ivars should only be used from inside the library/
framework itself, and only for very good reason.
- public ivars should not exist!
Moreover ivars are never documented.
Then GNUstep users should never meet this problem. If they do then I
think this is their own choice.
Do i still miss something ?
/* Class in public interface.
*/
@interface LibraryClass: NSObject
{
@private
int _ivar1;
}
@end
/* Class in user application
*/
@interface MyClass : LibraryClass
{
NSString *name;
}
- (NSString*) name;
- (void) setName: (NSString*)n;
@end
Now, we release a new version of the library ...
/* Class in public interface.
*/
@interface LibraryClass: NSObject
{
@private
int _ivar1;
int _ivar2;
}
@end
When the user application creates an instance of MyClass, the runtime
is asked for the size of the class in order to allocate it ... and the
size if the size of the ivars of NSObject ('isa') plus the size of the
ivars of LibraryClass (_ivar1 and _ivar2) plus the size of the ivars
of MyClass (name).
When application code then calls [MyClass-setName:] on the newly
created instance, it attempts to assign a value to its 'name' ivar,
but it was compiled thinking that the ivar layout was
{
Class isa;
int _ivar1;
NSString *name;
}
but the actual layout at runtime is
{
Class isa;
int _ivar1;
int _ivar2;
NSString *name;
}
so the assignment actually overwrites _ivar2
David's non-fragile ivar mechanism essentially overcomes this by
having the code look up at runtime what the offset to 'name' should
be, rather than depending on the value produced at compile time. This
produces some additional runtime overheads (cleverly kept to a
minimum), but is fairly quick.
I don't know the technical details, but David could probably explain
or point you to a good explanation on the web.
_______________________________________________
Gnustep-dev mailing list
Gnustep-dev@gnu.org
http://lists.gnu.org/mailman/listinfo/gnustep-dev