memory management question
-
My app reads lots of TIFFs from disk. As it does this, I can see (with
MemoryStick) that the amount of the computer's "inactive" memory goes way up
- that is, more and more RAM is being allocated to "inactive" memory, until
RAM fills up (the amount of "free" memory drops to near zero). When the app
is done, this memory is not given back.
My guess is that this memory is a caching of the tiff files from disk. The
reason for this guess is in part that if I run my app again, it all happens
much faster and there is no sound of the disk being read.
What I'd like to do is give back the memory after I'm done with each file. I
have tried all the Cocoa tricks I can think of (autorelease pools
everywhere, explicit init and release wherever possible, and so forth) but
nothing helps. In fact, this is apparently not a Cocoa memory management
issue - I'm not leaking memory, AFAIK - it's a system memory management
issue. It's like I'm fighting the virtual memory system.
Is what I'd like to do reasonable / possible? Thx - m.
--
matt neuburg, phd = <matt...>, http://www.tidbits.com/matt/
pantes anthropoi tou eidenai oregontai phusei
AppleScript: the Definitive Guide! NOW SHIPPING...! (Finally.)
http://www.amazon.com/exec/obidos/ASIN/0596005571/somethingsbymatt
Subscribe to TidBITS! It's free and smart. http://www.tidbits.com/
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
On Mar 18, 2004, at 6:36 PM, matt neuburg wrote:
> In fact, this is apparently not a Cocoa memory management
> issue - I'm not leaking memory, AFAIK - it's a system memory management
> issue. It's like I'm fighting the virtual memory system.
Have you tried using memory-mapped files to read your TIFFs? -Ii.e.
NSData's +dataWithContentsOfMappedFile: or
-initWithContentsOfMappedFile:, or even the low-level mmap() function.
My thinking is that, because memory-mapped files are directly mapped
into your app's virtual memory space, there's no system buffer to be
held when the file is closed.
This assumes, naturally, that your files are <2GB. Bigger files than
that won't be mmap()-able until we have 64-bit address spaces.
sherm--
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
On Thu, 18 Mar 2004 20:54:24 -0500, Sherm Pendley <sherm...> said:
> On Mar 18, 2004, at 6:36 PM, matt neuburg wrote:
>
>> In fact, this is apparently not a Cocoa memory management
>> issue - I'm not leaking memory, AFAIK - it's a system memory management
>> issue. It's like I'm fighting the virtual memory system.
>
> Have you tried using memory-mapped files to read your TIFFs?
Yes; in fact, that's how I've been doing it all along, and one of the things
I recently tried was using initWithContentsOfFile instead of
initWithContentsOfMappedFile. It made no difference. m.
--
matt neuburg, phd = <matt...>, http://www.tidbits.com/matt/
pantes anthropoi tou eidenai oregontai phusei
AppleScript: the Definitive Guide! NOW SHIPPING...! (Finally.)
http://www.amazon.com/exec/obidos/ASIN/0596005571/somethingsbymatt
Subscribe to TidBITS! It's free and smart. http://www.tidbits.com/
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
On 19/3/04 4:58 pm, matt neuburg <matt...> wrote:
> On Thu, 18 Mar 2004 20:54:24 -0500, Sherm Pendley <sherm...> said:
>> On Mar 18, 2004, at 6:36 PM, matt neuburg wrote:
>>
>>> In fact, this is apparently not a Cocoa memory management
>>> issue - I'm not leaking memory, AFAIK - it's a system memory management
>>> issue. It's like I'm fighting the virtual memory system.
>>
>> Have you tried using memory-mapped files to read your TIFFs?
>
> Yes; in fact, that's how I've been doing it all along, and one of the things
> I recently tried was using initWithContentsOfFile instead of
> initWithContentsOfMappedFile. It made no difference. m.
The OS will still cache mmapped files unless you tell it not to. There was a
discussion about techniques for this on <darwin-development...>
last year; I'd recommend you search its archives for messages with "mmap" in
the title.
Cheers,
Chris
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
On Mar 18, 2004, at 3:36 PM, matt neuburg wrote:
> My app reads lots of TIFFs from disk. As it does this, I can see (with
> MemoryStick) that the amount of the computer's "inactive" memory goes
> way up
> - that is, more and more RAM is being allocated to "inactive" memory,
> until
> RAM fills up (the amount of "free" memory drops to near zero). When
> the app
> is done, this memory is not given back.
This is normal, it is the UBC (universal buffer cache) attempting to
cache data that may possibly be used again in an attempt to avoid disk
or network I/O.
> My guess is that this memory is a caching of the tiff files from disk.
> The
> reason for this guess is in part that if I run my app again, it all
> happens
> much faster and there is no sound of the disk being read.
>
> What I'd like to do is give back the memory after I'm done with each
> file. I
> have tried all the Cocoa tricks I can think of (autorelease pools
> everywhere, explicit init and release wherever possible, and so forth)
> but
> nothing helps.
You really don't need to give it "back" because it isn't really taken.
The UBC is simply using available pages in physical RAM to hold onto
information. If someone needs a page and a free one isn't available
then an inactive one will get used (since it is caching file data no
page out is needed, it just zeros it and returns the page like it would
if it was a free page). You really don't need to concern yourself with
this (unless you really really want to avoid using the UBC for some
reason).
Having lots of free RAM on your system not being used for something is
a waste of RAM and this caching attempts to make the most of it without
causing issues because if memory is needed for active data inactive
stuff is tossed out the window.
> In fact, this is apparently not a Cocoa memory management
> issue - I'm not leaking memory, AFAIK - it's a system memory management
> issue. It's like I'm fighting the virtual memory system.
>
> Is what I'd like to do reasonable / possible? Thx - m.
If you are dealing with mapped files I believe you can tell the OS to
by pass caching it in the UBC.
-Shawn
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
On Fri, 19 Mar 2004 14:21:29 -0800, Shawn Erickson <shawn...>
said:
> On Mar 18, 2004, at 3:36 PM, matt neuburg wrote:
>
>> My app reads lots of TIFFs from disk. As it does this, I
>> can see (with MemoryStick) that the amount of the
>> computer's "inactive" memory goes way up - that is, more
>> and more RAM is being allocated to "inactive" memory,
>> until RAM fills up (the amount of "free" memory drops to
>> near zero). When the app is done, this memory is not
>> given back.
>
> This is normal, it is the UBC (universal buffer cache)
> attempting to cache data that may possibly be used again
> in an attempt to avoid disk or network I/O.
>>
>> What I'd like to do is give back the memory after I'm
>> done with each file. I have tried all the Cocoa tricks I
>> can think of (autorelease pools everywhere, explicit
>> init and release wherever possible, and so forth) but
>> nothing helps.
>
> You really don't need to give it "back" because it isn't
> really taken. The UBC is simply using available pages in
> physical RAM to hold onto information. If someone needs a
> page and a free one isn't available then an inactive one
> will get used (since it is caching file data no page out
> is needed, it just zeros it and returns the page like it
> would if it was a free page).
That is a lovely theory, and perhaps some varieties of Unix work that way,
but on Mac OS X that is not in fact what happens. What happens is that the
"inactive" stuff in memory accumulates and overwhelms physical RAM and
pageouts start to happen, and swapfiles are created. On my machine, a single
run of my program, reading, say, a dozen large TIFFs, can easily cause two
additional swapfiles to be created. This is *not* due to a leak in my
program! The amount of "wired" and "active" RAM in use does not increase.
This is all due to "inactive" RAM swelling. The mere act of reading large
TIFFs from disk seems to cause the problem.
The problem is alleviated somewhat if the user happens to have extremely
large amounts of RAM, but that is not really acceptable. The user really
should not need more RAM to run my program than is necessary to hold in
memory two images: the TIFF currently being read, and the image I am
creating (I'm making a thumbnail of each successive TIFF and "pasting" the
thumbnail into my image).
Once a TIFF has been read from disk, it will not be read again. The system
is wrong to cache it; this is a false optimization. Thus, I am looking for a
way to get the system to "give back" the RAM occupied by each TIFF after I
am done with it. m.
--
matt neuburg, phd = <matt...>, http://www.tidbits.com/matt/
pantes anthropoi tou eidenai oregontai phusei
AppleScript: the Definitive Guide! NOW SHIPPING...! (Finally.)
http://www.amazon.com/exec/obidos/ASIN/0596005571/somethingsbymatt
Subscribe to TidBITS! It's free and smart. http://www.tidbits.com/
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
How about using something like this on the file descriptors?
fcntl(fd, F_NOCACHE, 1);
fcntl(fd, F_RDAHEAD, 1);
... it seems to work for me, on Panther.
On Mar 20, 2004, at 11:05 AM, matt neuburg wrote:
> Once a TIFF has been read from disk, it will not be read again. The_______________________________________________
> system
> is wrong to cache it; this is a false optimization. Thus, I am looking
> for a
> way to get the system to "give back" the RAM occupied by each TIFF
> after I
> am done with it. m.
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
On 3/20/04 at roughly 9:56 AM, thus spake Michael Rothwell
<michael...>:
> How about using something like this on the file descriptors?
>
> fcntl(fd, F_NOCACHE, 1);
> fcntl(fd, F_RDAHEAD, 1);
>
> .... it seems to work for me, on Panther.
That is absolutely perfect. I can't thank you enough. You've no idea how
much experimenting and tweaking I've done over the past couple of months
with this app, trying to change its memory-management behavior from within
Cocoa itself. It seemed hopeless, and I worried that the app would just
never be viable. You've breathed new life into the whole project. My client
is going to be reeeeeally happy. m.
PS I take it that there is no downside to this that I need to watch out for?
I'm not, with these fcntl() calls, altering anything that I need to reset
afterwards, am I? Presently I am just creating the NSFileHandle from a
pathname, making the fcntl() calls, reading all the data, then sending
-closeFile to the NSFileHandle and then letting the NSFileHandle get
released in the usual way.
> On Mar 20, 2004, at 11:05 AM, matt neuburg wrote:--
>> Once a TIFF has been read from disk, it will not be read
>> again. The system is wrong to cache it; this is a false
>> optimization. Thus, I am looking for a way to get the
>> system to "give back" the RAM occupied by each TIFF
>> after I am done with it. m.
matt neuburg, phd = <matt...>, http://www.tidbits.com/matt/
pantes anthropoi tou eidenai oregontai phusei
AppleScript: the Definitive Guide! NOW SHIPPING...! (Finally.)
http://www.amazon.com/exec/obidos/ASIN/0596005571/somethingsbymatt
Subscribe to TidBITS! It's free and smart. http://www.tidbits.com/
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
On Mar 20, 2004, at 8:05 AM, matt neuburg wrote:
> On Fri, 19 Mar 2004 14:21:29 -0800, Shawn Erickson
> <shawn...>
> said:
>> On Mar 18, 2004, at 3:36 PM, matt neuburg wrote:
>>
>>> My app reads lots of TIFFs from disk. As it does this, I
>>> can see (with MemoryStick) that the amount of the
>>> computer's "inactive" memory goes way up - that is, more
>>> and more RAM is being allocated to "inactive" memory,
>>> until RAM fills up (the amount of "free" memory drops to
>>> near zero). When the app is done, this memory is not
>>> given back.
>>
>> This is normal, it is the UBC (universal buffer cache)
>> attempting to cache data that may possibly be used again
>> in an attempt to avoid disk or network I/O.
>>>
>>> What I'd like to do is give back the memory after I'm
>>> done with each file. I have tried all the Cocoa tricks I
>>> can think of (autorelease pools everywhere, explicit
>>> init and release wherever possible, and so forth) but
>>> nothing helps.
>>
>> You really don't need to give it "back" because it isn't
>> really taken. The UBC is simply using available pages in
>> physical RAM to hold onto information. If someone needs a
>> page and a free one isn't available then an inactive one
>> will get used (since it is caching file data no page out
>> is needed, it just zeros it and returns the page like it
>> would if it was a free page).
>
> That is a lovely theory, and perhaps some varieties of Unix work that
> way,
> but on Mac OS X that is not in fact what happens. What happens is that
> the
> "inactive" stuff in memory accumulates and overwhelms physical RAM and
> pageouts start to happen, and swapfiles are created. On my machine, a
> single
> run of my program, reading, say, a dozen large TIFFs, can easily cause
> two
> additional swapfiles to be created. This is *not* due to a leak in my
> program! The amount of "wired" and "active" RAM in use does not
> increase.
> This is all due to "inactive" RAM swelling. The mere act of reading
> large
> TIFFs from disk seems to cause the problem.
What problem does this page-out cause the user? What OS are you seeing
this on? If panther then two additional swap files likely amount to
around 384 MB, is that what you see?
Anyway I am curious on what is being paged out. Could you provide a
copy of your application so one could monitor things?
It is likely what is being paged out is some type data that is not
backed by a file and is tagged such that it is considered page-able
even in the case of caching in the UBC.
> The problem is alleviated somewhat if the user happens to have
> extremely
> large amounts of RAM, but that is not really acceptable. The user
> really
> should not need more RAM to run my program than is necessary to hold in
> memory two images: the TIFF currently being read, and the image I am
> creating (I'm making a thumbnail of each successive TIFF and "pasting"
> the
> thumbnail into my image).
Is it really a problem, as in a performance issue, or is it something
you would just like to avoid?
> Once a TIFF has been read from disk, it will not be read again. The
> system
> is wrong to cache it; this is a false optimization.
If that is the case then tell the OS this fact, it cannot know your
usage intent up front. In most situations a once used file is likely to
be used again so that is the default optimization in most cases (almost
all OSes today have this type of default caching mode).
> Thus, I am looking for a
> way to get the system to "give back" the RAM occupied by each TIFF
> after I
> am done with it. m.
It looks like Michael pointed out the fcntl to use, I could not recall
of the top of my head when I sent my prior message. If the pattern is
as you described I would recommend that you avoid the UBC so as to not
pollute it with items that are likely only to be read once.
If you are writing out new TIFFs are you doing that in one shot or
writing out data in pieces? If that later you may want to set the file
size up front to avoid file growth overhead and better avoid
fragmentation of the file.
-Shawn
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
I need to see if I "get" ObjC's memory management scheme yet:
I have a method that returns an autoreleased NSString*; in an
instance of a class I store that returned value in an ivar; I then
store that class instance in an NSArray.
Putting the class instance into the array increases its (the class
instance) refcount, right? What about the refcount of the NSString
ivar contained in that class? Not touched, right? I have to
explicitly retain/release that, correct? What's the easiest way to
managed that--"retain" in my setter method and override "-dealloc" in
my class and release the NSString* ivar there?
What about something like:
line = [line stringByTrimmingCharactersInSet:...];
where line is also an autoreleased NSString*? Since the "line" on
the RHS is already in an autorelease pool, it'll get released when
the pool does its thing, right? And then the new value assigned to
the lvalue "line" gets autoreleased (eventually), right?
I have a feeling I'm going to get quite the memory management
education when I finally let my nested loops run at full tilt--each
is bounded by a custom NSAutoreleasePool; I'm hoping to shortcut that
a bit by learning from the masters around here...
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
At 12:40 PM -0500 3/24/04, Randall Meadows wrote:
> line = [line stringByTrimmingCharactersInSet:...];
I now notice that NSMutableString has setString: available. Would it
be more efficient to do
[[line setString:[line stringByTrimmingCharactersInSet:...];
instead of creating a new object each time? That should trim down
the number of objects in my autorelease pool, right (which, at times,
can be a lot, which is why I'm using a number of nested autorelease
pools)?
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
On 24 Mar 2004, at 17:40, Randall Meadows wrote:
> I need to see if I "get" ObjC's memory management scheme yet:
>
> I have a method that returns an autoreleased NSString*; in an instance
> of a class I store that returned value in an ivar; I then store that
> class instance in an NSArray.
>
> Putting the class instance into the array increases its (the class
> instance) refcount, right? What about the refcount of the NSString
> ivar contained in that class? Not touched, right? I have to
> explicitly retain/release that, correct? What's the easiest way to
> managed that--"retain" in my setter method and override "-dealloc" in
> my class and release the NSString* ivar there?
Yes, although you need to be careful in your setter to remember to
-release the existing ivar---remember, BTW, that it's harmless sending
messages to nil, so something simple like:
- (void)setStringValue:(NSString *)string
{
[string retain];
[myString release];
myString = string;
}
will work just fine (although it obviously isn't thread-safe).
Incidentally, for strings and other objects with mutable forms, you
might consider whether you really want
- (void)setStringValue:(NSString *)string
{
string = [string copy];
[myString release];
myString = string;
}
For immutable objects, -copy tends to be implemented as a -retain, but
for mutable objects it will ensure that you get a snapshot of the
object's value, rather than something that might be changed outside the
control of your object.
The other thing to note is that it's possible to slip-up if you don't
think carefully about the order of your -retain and -release; consider
the case where someone writes
[myObject setStringValue:[myObject stringValue]];
if we had written
- (void)setStringValue:(NSString *)string
{
[myString release];
myString = [string retain];
}
then the call above would cause a crash because the object in "string"
has been released (by the [myString release]) more times than it has
been retained and has therefore been deallocated.
(You might think that nobody will ever write a call like the one above,
but remember that the pointer to your string might be stored by other
objects, especially as -copy just does a -retain for immutable string
objects. It's actually quite easy for you to end-up being passed the
same pointer you've already got.)
> What about something like:
>
> line = [line stringByTrimmingCharactersInSet:...];
>
> where line is also an autoreleased NSString*? Since the "line" on the
> RHS is already in an autorelease pool, it'll get released when the
> pool does its thing, right? And then the new value assigned to the
> lvalue "line" gets autoreleased (eventually), right?
If the object in line is already autoreleased, then yes, there is no
leak here.
> At 12:40 PM -0500 3/24/04, Randall Meadows wrote:
>
>> line = [line stringByTrimmingCharactersInSet:...];
>
> I now notice that NSMutableString has setString: available. Would it
> be more efficient to do
>
> [[line setString:[line stringByTrimmingCharactersInSet:...];
>
> instead of creating a new object each time?
No. You're still creating just as many objects, but now you've got a
string copy operation as well. If you're worried about too many
objects floating around, you can always use additional autorelease
pools to clean them up as and when necessary. Alternatively, you can
immediately release any individual autoreleased object by doing
[[someObject retain] release];
(The -retain increments the reference count, removing it from the
autorelease pool, then the -release triggers the deallocation of the
object.)
BTW, if I were you, I'd write your program before worrying that you're
creating too many objects; unless there's some really obvious area
where it's going to cause trouble (e.g. you have a loop that goes
around ten million times, creating four autoreleased strings per
iteration), then you shouldn't worry about creating temporary objects
too much until you get to the optimisation stage.
Take a look at my FAQ if you haven't already, as it gives a few hints
on memory allocation. It's here:
http://www.alastairs-place.net/cocoa/faq.txt
It does sound like you've grasped the basics, though.
Kind regards,
Alastair.
--
http://www.alastairs-place.net
[demime 0.98b removed an attachment of type application/pkcs7-signature which had a name of smime.p7s]
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
You do realize that what you're doing is creating a new object, then
using it to modify the current object? So you're not cutting down on
your object usage at all, but in fact you are making it slightly slower
(since instead of just replacing the object you're modifying it). This
also requires your string to be mutable.
On Mar 24, 2004, at 1:43 PM, Randall Meadows wrote:
> At 12:40 PM -0500 3/24/04, Randall Meadows wrote:
>
>> line = [line stringByTrimmingCharactersInSet:...];
>
> I now notice that NSMutableString has setString: available. Would it
> be more efficient to do
>
> [[line setString:[line stringByTrimmingCharactersInSet:...];
>
> instead of creating a new object each time? That should trim down the
> number of objects in my autorelease pool, right (which, at times, can
> be a lot, which is why I'm using a number of nested autorelease
> pools)?
--
Kevin Ballard
<kevin...>
http://www.tildesoft.com
http://kevin.sb.org
[demime 0.98b removed an attachment of type application/pkcs7-signature which had a name of smime.p7s]
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
Alastair,
On Wednesday, Mar 24, 2004, at 20:14 Europe/Prague, Alastair Houghton
wrote:
> something simple like:
>
> - (void)setStringValue:(NSString *)string
> {
> [string retain];
> [myString release];
> myString = string;
> }
>
> will work just fine...
... in most cases, but can fail too, presumed a plain getter of kind
-(NSString*)stringValue { return myString; }
is used. The problem may be risen by the fact someone can use the
getter, then use some code which happens to call the setter, and then
use the value from the getter:
NSString *s=[foo stringValue];
// some code here which, whatever indirectly, calls the setter
[s length]; // a crasher
For this reason, it's generally better if one of the accessors uses
autorelease--it may be either one. It is more safe (but of course, also
*much* less efficient) if the getter is autoreleasing (using the
pattern [[ivar retain] autorelease]); in most cases probably it is
sufficient that the setter is autoreleasing ([ivar autorelease];
ivar=[newValue retain];).
Note also that either the setter should be used to nil the ivar in
dealloc (which is IMHO considerably preferrable), or, unless the getter
is autoreleasing, in dealloc also autorelease should be used (insted of
release) to free the ivar's contents.
In 2002 this along with all the possibilities (including the black
magic of thread-safe accessors) was discussed to death and over again,
triple times: should be in the archives, subjects "Accessor methods and
(auto)release: conclusion" or "Accessors (can we close it this way?)".
---
Ondra Hada
OCSoftware: <ocs...> http://www.ocs.cz
private <ondra...> http://www.ocs.cz/oc
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
On Mar 24, 2004, at 1:24 PM, Ondra Cada wrote:
> In 2002 this along with all the possibilities (including the blackThere's also a summary article at:
> magic of thread-safe accessors) was discussed to death and over again,
> triple times: should be in the archives, subjects "Accessor methods
> and (auto)release: conclusion" or "Accessors (can we close it this
> way?)".
>
<http://www.stepwise.com/Articles/Technical/2002-06-11.01.html>
mmalc
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
At 7:14 PM +0000 3/24/04, Alastair Houghton wrote:
> remember, BTW, that it's harmless sending messages to nil,
...
> Alternatively, you can immediately release any individual
> autoreleased object by doing
>
> [[someObject retain] release];
>
> (The -retain increments the reference count, removing it from the
> autorelease pool, then the -release triggers the deallocation of the
> object.)
When an object gets deallocated, is it then set to nil? In the above
sample, is then "someObject" == nil? Or does that variable contain
an invalid (unallocated) memory address, as would a similar pointer
that has been free'd in POC (plain ol' C)?
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
On 24 Mar 2004, at 21:24, Ondra Cada wrote:
> Alastair,
>
> On Wednesday, Mar 24, 2004, at 20:14 Europe/Prague, Alastair Houghton
> wrote:
>
>> something simple like:
>>
>> - (void)setStringValue:(NSString *)string
>> {
>> [string retain];
>> [myString release];
>> myString = string;
>> }
>>
>> will work just fine...
>
> ... in most cases, but can fail too, presumed a plain getter of kind
>
> -(NSString*)stringValue { return myString; }
>
> is used. The problem may be risen by the fact someone can use the
> getter, then use some code which happens to call the setter, and then
> use the value from the getter:
>
> NSString *s=[foo stringValue];
> // some code here which, whatever indirectly, calls the setter
> [s length]; // a crasher
Agreed and I'm well aware of the argument. Personally I follow the
approach advocated by Marco and Marcel, for instance in this thread
http://cocoa.mamasam.com/COCOADEV/2002/08/1/41613.php
since I find that I don't write code like the example you just gave,
and avoiding extraneous autoreleases is a performance win. Also as has
been pointed-out before, if you do accidentally write such code, you'll
normally cause a crash, which makes it pretty easy to debug.
BTW, autoreleasing in the setter isn't a solution to the problem,
because someone could wrap an autorelease pool around the call to the
-setStringValue: method, which would result in the same crash you talk
about with the simple methods.
Kind regards,
Alastair.
--
http://www.alastairs-place.net
[demime 0.98b removed an attachment of type application/pkcs7-signature which had a name of smime.p7s]
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
On 24.03.2004, at 20:14, Alastair Houghton wrote:
> pools to clean them up as and when necessary. Alternatively, you can
> immediately release any individual autoreleased object by doing
>
> [[someObject retain] release];
>
> (The -retain increments the reference count, removing it from the
> autorelease pool, then the -release triggers the deallocation of the
> object.)
I find this a little bit disturbing because I was under the impression
that a retain/release pair would leave the object in the exact same
state regarding memory management.
I was not able to find a hint in the docs about this fact,
so I think we are at (the somewhat unlikely) risk that:
id autoreleasedThingy = [SomeThing thingy];
// assuming there is a hidden retain/release inside
[ThirdPartyClass damageThingy: autoreleasedThingy];
NSLog(@"at: %@", autoreleasedThingy);
will crash ?
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
Alastair,
On Wednesday, Mar 24, 2004, at 23:10 Europe/Prague, Alastair Houghton
wrote:
> Also as has been pointed-out before, if you do accidentally write such
> code, you'll normally cause a crash, which makes it pretty easy to
> debug
Well, also, as has been pointed-out before, if you do accidentally
write such code, there's a quite non-trivial probability you made a
ticking bomb which just *happens* not to crash now, but will with a new
framework/engine/library/bundle/haxie release... creating so one
*extremely* hard-to-find bitch problem.
Nevertheless, I take it you are well aware of this part of the argument
too, and am writing this message actually just for the benefit of other
readers (who are truly invited to check the archives, where all the
arguments of both sides are stated--many times over ;)--and judge for
themselves whether they generally prefer safety or efficiency).
At the very least (again for the benefit of other readers, of course)
it should be strongly pointed out that so far as one uses code with
plain getters (and *especially* if the setters are just releasing
/instead of autoreleasing/), one should be *very* careful with *any*
code of kind
id o=[foo getter];
// any code here (*)
// o used now
and wherever there is the slightest suspicion the (*) code may,
whatever indirectly or in future releases, cause the setter to be
called, one should always use the safe pattern
id o=[[[foo getter] retain] autorelease];
// any code here
// o used now
instead.
---
Ondra Hada
OCSoftware: <ocs...> http://www.ocs.cz
private <ondra...> http://www.ocs.cz/oc
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
Randall,
On Wednesday, Mar 24, 2004, at 23:02 Europe/Prague, Randall Meadows
wrote:
>> [[someObject retain] release];
>
> When an object gets deallocated, is it then set to nil?
Never. You do that yourself when appropriate.
> In the above sample, is then "someObject" == nil?
Besides, in the above sample, the object is not, repeat *NOT*
deallocated. Quite the contrary: its lifespan is (potentially) expanded
so that it exists *at least* till the current autorelease pool is freed.
> Or does that variable contain an invalid (unallocated) memory address,
> as would a similar pointer that has been free'd in POC (plain ol' C)?
In cases you truly release the object, ie. the simplest
[someObject release];
it is *exactly so*. If you forget to nil the variable, you are in for a
nasty surprise. Not only the app may crash: that's the better case.
Worse, another object may occupy the address meantime!
---
Ondra Hada
OCSoftware: <ocs...> http://www.ocs.cz
private <ondra...> http://www.ocs.cz/oc
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
On 24.03.2004, at 23:02, Randall Meadows wrote:
> When an object gets deallocated, is it then set to nil? In the above
> sample, is then "someObject" == nil? Or does that variable contain an
> invalid (unallocated) memory address, as would a similar pointer that
> has been free'd in POC (plain ol' C)?
It will contain an invalid address.
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
On 24 Mar 2004, at 22:36, Ondra Cada wrote:
> Randall,
>
> On Wednesday, Mar 24, 2004, at 23:02 Europe/Prague, Randall Meadows
> wrote:
>
>>> [[someObject retain] release];
>>
>> When an object gets deallocated, is it then set to nil?
>
> Never. You do that yourself when appropriate.
>
>> In the above sample, is then "someObject" == nil?
>
> Besides, in the above sample, the object is not, repeat *NOT*
> deallocated. Quite the contrary: its lifespan is (potentially)
> expanded so that it exists *at least* till the current autorelease
> pool is freed.
Indeed. As I already posted (although it hasn't got there yet), I was
mistaken. I'd be surprised if the lifespan were expanded unless you
did another -autorelease though.
Kind regards,
Alastair.
--
http://www.alastairs-place.net
[demime 0.98b removed an attachment of type application/pkcs7-signature which had a name of smime.p7s]
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
On 24 Mar 2004, at 22:32, Ondra Cada wrote:
> Nevertheless, I take it you are well aware of this part of the
> argument too, and am writing this message actually just for the
> benefit of other readers (who are truly invited to check the archives,
> where all the arguments of both sides are stated--many times over ;)
Indeed. That's why I put a link to the archives in my previous message.
[snip]
> and wherever there is the slightest suspicion the (*) code may,
> whatever indirectly or in future releases, cause the setter to be
> called, one should always use the safe pattern
>
> id o=[[[foo getter] retain] autorelease];
> // any code here
> // o used now
or
id o = [[foo getter] retain];
// code here
// o used now
[o release];
which avoids an unnecessary autorelease :-)
Kind regards,
Alastair.
--
http://www.alastairs-place.net
[demime 0.98b removed an attachment of type application/pkcs7-signature which had a name of smime.p7s]
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
Alastair,
On Thursday, Mar 25, 2004, at 00:20 Europe/Prague, Alastair Houghton
wrote:
> id o = [[foo getter] retain];
> // code here
> // o used now
> [o release];
>
> which avoids an unnecessary autorelease :-)
... making the code also a possible leaker (which is not too
important), and *MUCH* more error-prone, which is generally *far far*
worse than the very slight autorelease overhead.
No, don't. This is generally a wrong pattern.
---
Ondra Hada
OCSoftware: <ocs...> http://www.ocs.cz
private <ondra...> http://www.ocs.cz/oc
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
Bjoern,
On Wednesday, Mar 24, 2004, at 23:20 Europe/Prague, Bjoern Kriews wrote:
>> [[someObject retain] release];
>>
>> (The -retain increments the reference count, removing it from the
>> autorelease pool, then the -release triggers the deallocation of the
>> object.)
>
> I find this a little bit disturbing because I was under the impression
> that a retain/release pair would leave the object in the exact same
> state regarding memory management.
Would. I am *terribly sorry*; the code should have been
[[someObject retain] autorelease];
(which self-evidently was meant to by the original writer, and I,
supposing so, did not note there's the mistake.)
So, please, re-read my previous post supposing there indeed was the
autorelease!
---
Ondra Hada
OCSoftware: <ocs...> http://www.ocs.cz
private <ondra...> http://www.ocs.cz/oc
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
<snip>
> pools to clean them up as and when necessary. Alternatively, you can<snip>
> immediately release any individual autoreleased object by doing
>
> [[someObject retain] release];
>
> (The -retain increments the reference count, removing it from the
> autorelease pool, then the -release triggers the deallocation of the
> object.)
This is the first I've ever heard that retain removes an object from
the autorelease pool. How does it know that the object is even *in* an
autorelease pool? And which pool? More info please.
Thanks,
Glen
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
On Mar 24, 2004, at 11:14 AM, Alastair Houghton wrote:
> Alternatively, you can
> immediately release any individual autoreleased object by doing
>
> [[someObject retain] release];
>
> (The -retain increments the reference count, removing it from the
> autorelease pool, then the -release triggers the deallocation of the
> object.)
Outlining what you said in the above...
1) allocated -> retain count = 1
2) autorelease -> retain count = 1 (the release is pending)
3a) retain -> retain count = 2
3b) retain -> remove object from autorelease pool (pending release is
canceled)
4) release -> retain count = 1
If it does exactly what you say in the above then you are left with an
object that will leak since it has an unbalanced retain.
Did you mean instead something like the following...
1) allocated -> retain count = 1
2) autorelease -> retain count = 1 (the release is pending)
3) retain -> remove object from autorelease pool (one instance of it in
the pool)
4) release -> retain count = 0
5) dealloc
...or what more likely really happens...
1) allocated -> retain count = 1
2) autorelease -> retain count = 1 (the release is pending)
3) retain -> retain count = 2
4) release -> retain count = 1
5) release -> retain count = 0 (release sent by autorelease pool)
6) dealloc
-Shawn
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
>> (The -retain increments the reference count, removing it from the
>> autorelease pool, then the -release triggers the deallocation of the
>> object.)
>
> This is the first I've ever heard that retain removes an object from
> the autorelease pool. How does it know that the object is even *in* an
> autorelease pool? And which pool? More info please.
I'm pretty sure they are mistaken. Retaining an object doesn't remove
it from any autorelease pools it's in.. if it did, each retain would be
worth 2 or more retains, so you'd leak gratuitously.
You could, I suppose, search all available autorelease pools for the
object, and only if it's not in one actually increment it's retain
count, but there are numerous problems with this, not the least of
which is performance and trying to ensure you check every pool.
Wade Tregaskis
-- Sed quis custodiet ipsos custodes?
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
On 25 mar 2004, at 00.41, Glen Simmons wrote:
> <snip>
>> pools to clean them up as and when necessary. Alternatively, you can
>> immediately release any individual autoreleased object by doing
>>
>> [[someObject retain] release];
>>
>> (The -retain increments the reference count, removing it from the
>> autorelease pool, then the -release triggers the deallocation of the
>> object.)
> <snip>
>
> This is the first I've ever heard that retain removes an object from
> the autorelease pool. How does it know that the object is even *in* an
> autorelease pool? And which pool? More info please.
Why don't we try it out?
malte% cat autorelease.m
#import <Foundation/Foundation.h>
@interface Dummy : NSObject
@end
@implementation Dummy
- (id)retain {
NSLog(@"dummy retain");
return [super retain];
}
- (oneway void)release {
NSLog(@"dummy release");
[super release];
}
@end
int main() {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
id s = nil;
NSLog(@"creating");
s = [[Dummy alloc] init];
NSLog(@"autoreleasing");
[s autorelease];
NSLog(@"retain/release");
[[s retain] release];
NSLog(@"releasing pool");
[pool release];
exit(0);
return 0;
}
malte% ./autorelease
2004-03-25 08:11:31.051 autorelease[688] creating
2004-03-25 08:11:31.054 autorelease[688] autoreleasing
2004-03-25 08:11:31.055 autorelease[688] retain/release
2004-03-25 08:11:31.056 autorelease[688] dummy retain
2004-03-25 08:11:31.057 autorelease[688] dummy release
2004-03-25 08:11:31.058 autorelease[688] releasing pool
2004-03-25 08:11:31.060 autorelease[688] dummy release
Cheerio,
Malte
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
(I meant to send this to the list yesterday, but missed the "Reply to
All" button when writing it.)
On 24 Mar 2004, at 22:20, Bjoern Kriews wrote:
> On 24.03.2004, at 20:14, Alastair Houghton wrote:
>> pools to clean them up as and when necessary. Alternatively, you can
>> immediately release any individual autoreleased object by doing
>>
>> [[someObject retain] release];
>>
>> (The -retain increments the reference count, removing it from the
>> autorelease pool, then the -release triggers the deallocation of the
>> object.)
>
> I find this a little bit disturbing because I was under the impression
> that a retain/release pair would leave the object in the exact same
> state regarding memory management.
Apologies, I was incorrect. As was pointed-out by Kurt Revis off-list,
this does not, of course, remove the object from the autorelease pool.
(I was confusing the behaviour of the autorelease mechanism with
something very similar that I wrote myself a while back that solved a
very similar problem.)
Kind regards,
Alastair.
--
http://www.alastairs-place.net
[demime 0.98b removed an attachment of type application/pkcs7-signature which had a name of smime.p7s]
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
On 24 Mar 2004, at 23:40, Ondra Cada wrote:
> Bjoern,
>
> On Wednesday, Mar 24, 2004, at 23:20 Europe/Prague, Bjoern Kriews
> wrote:
>
>>> [[someObject retain] release];
>>>
>>> (The -retain increments the reference count, removing it from the
>>> autorelease pool, then the -release triggers the deallocation of the
>>> object.)
>>
>> I find this a little bit disturbing because I was under the impression
>> that a retain/release pair would leave the object in the exact same
>> state regarding memory management.
>
> Would. I am *terribly sorry*; the code should have been
>
> [[someObject retain] autorelease];
>
> (which self-evidently was meant to by the original writer, and I,
> supposing so, did not note there's the mistake.)
No, don't apologise. The original message was wrong.
Kind regards,
Alastair.
--
http://www.alastairs-place.net
[demime 0.98b removed an attachment of type application/pkcs7-signature which had a name of smime.p7s]
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
On 24 Mar 2004, at 23:41, Glen Simmons wrote:
>
> <snip>
>> pools to clean them up as and when necessary. Alternatively, you can
>> immediately release any individual autoreleased object by doing
>>
>> [[someObject retain] release];
>>
>> (The -retain increments the reference count, removing it from the
>> autorelease pool, then the -release triggers the deallocation of the
>> object.)
> <snip>
>
> This is the first I've ever heard that retain removes an object from
> the autorelease pool. How does it know that the object is even *in* an
> autorelease pool? And which pool? More info please.
It doesn't. The original message was wrong. I thought I'd already
posted to the list correcting myself, but as it happens I missed the
"Reply to All" button.
Kind regards,
Alastair.
--
http://www.alastairs-place.net
[demime 0.98b removed an attachment of type application/pkcs7-signature which had a name of smime.p7s]
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
On 24 Mar 2004, at 23:52, Shawn Erickson wrote:
> On Mar 24, 2004, at 11:14 AM, Alastair Houghton wrote:
>
>> Alternatively, you can
>> immediately release any individual autoreleased object by doing
>>
>> [[someObject retain] release];
>>
>> (The -retain increments the reference count, removing it from the
>> autorelease pool, then the -release triggers the deallocation of the
>> object.)
>
> Outlining what you said in the above...
No, ignore it, it's wrong.
--
http://www.alastairs-place.net
[demime 0.98b removed an attachment of type application/pkcs7-signature which had a name of smime.p7s]
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
On 25 Mar 2004, at 00:23, Wade Tregaskis wrote:
>>> (The -retain increments the reference count, removing it from the
>>> autorelease pool, then the -release triggers the deallocation of the
>>> object.)
>>
>> This is the first I've ever heard that retain removes an object from
>> the autorelease pool. How does it know that the object is even *in*
>> an autorelease pool? And which pool? More info please.
>
> I'm pretty sure they are mistaken.
Yep. Apologies to anybody I managed to confuse, I was getting mixed-up
with something I wrote to do reference counting of message blocks
(where the equivalent of autorelease pools did have the semantic I
implied). Cocoa doesn't work that way.
Kind regards,
Alastair.
--
http://www.alastairs-place.net
[demime 0.98b removed an attachment of type application/pkcs7-signature which had a name of smime.p7s]
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
On 24 Mar 2004, at 23:38, Ondra Cada wrote:
> Alastair,
>
> On Thursday, Mar 25, 2004, at 00:20 Europe/Prague, Alastair Houghton
> wrote:
>
>> id o = [[foo getter] retain];
>> // code here
>> // o used now
>> [o release];
>>
>> which avoids an unnecessary autorelease :-)
>
> ... making the code also a possible leaker (which is not too
> important), and *MUCH* more error-prone, which is generally *far far*
> worse than the very slight autorelease overhead.
>
> No, don't. This is generally a wrong pattern.
I think this probably also constitutes part of the same argument. I
would use -autorelease if the code might throw exceptions (because it
obviates the need for handlers) or if the code where you wrote that
comment was long (although if you have a lot of code there, there might
be opportunities for refactoring).
If I were worried about this level of risk of errors (IMO not that
high), I'd be using Ada and not a C derivative.
Kind regards,
Alastair.
--
http://www.alastairs-place.net
[demime 0.98b removed an attachment of type application/pkcs7-signature which had a name of smime.p7s]
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
I know this thread has been dead for a few days, but it took me that long to
study it and all the referenced articles.
I have a question regarding the use of accessor methods for "object instance
variables", (which I prefer to call "objects within objects").
I understand the recommendation to use fancy setter methods, with their
pattern of retain, release, copy; and I also understand the arguments for
and against using autorelease there instead of release.
But I don't understand the recommendation to use the getter method:
- (NSSomeType*)foo
{
return foo;
}
and the advice to always use the getter method
[self foo]
instead of just a direct reference
foo
when using foo in other methods in the class.
What's the effective difference between these two expressions? All I can
see is that the getter has the overhead of a message, while the direct
reference does not and should run faster.
Jerry Krinock
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
On 27 Mar 2004, at 18:00, Jerry Krinock wrote:
> I don't understand the recommendation to use the getter method [snip]
> and the advice to always use the getter method [snip] instead of just
> a direct reference [snip] when using foo in other methods in the
> class.
>
> What's the effective difference between these two expressions? All I
> can
> see is that the getter has the overhead of a message, while the direct
> reference does not and should run faster.
The difference is that with the method in place, you can easily change
the implementation of your class (for instance, you may decide that
it's better to compute a value on the fly rather than keeping a copy in
each object). If you don't use the getter method, you may have to
change a lot more code.
The getter method also allows you to do other things, like log changes
to a property, which is pretty much impossible without using a
getter/setter approach.
I have to say that I do vary my implementations; for simple classes
whose implementation is unlikely to change and that are unlikely to be
subclassed, I often write direct references. For more complex classes,
or classes that might be subclassed, using the method approach is
certainly better.
Kind regards,
Alastair.
--
http://www.alastairs-place.net
[demime 0.98b removed an attachment of type application/pkcs7-signature which had a name of smime.p7s]
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
Am 27.03.2004 um 19:00 schrieb Jerry Krinock:
> What's the effective difference between these two expressions?
The difference is that [self foo] sends the foo message to the object
itself which might *not* be of class FooClass but could of a subclass
of it; so [self foo] possibly doesn't lead to the execution of your foo
method and subsequently might not return the foo instance variable.
Example:
@interface ClassA : NSObject
{
id foo;
}
- (id)foo
{
return foo;
}
- (void)setFoo:(id)newFoo
{
[foo autorelease];
foo = [newFoo retain];
}
- (void)checkFoo1 // first version - accessing the instance variable
directly
{
if (foo != nil) {
NSLog(@"foo is valid");
} else {
NSLog(@"foo is invalid");
}
}
- (void)checkFoo2 // second version - using accessor method
{
if ([self foo] != nil) {
NSLog(@"foo is valid");
} else {
NSLog(@"foo is invalid");
}
}
@end
@interface ClassB : ClassA
{
}
- (id)foo
{
// we decided that foo is of no use in this special subclass
return nil;
}
@end
Suppose something like this happens somewhere in the code:
ClassA *someObject = [[ClassB alloc] init]; // might be a return value
from some opaque method
[someObject setFoo:someOtherObject];
Now
[someObject checkFoo1];
will log "foo is valid" while
[someObject checkFoo2];
will result in "foo is invalid".
It is up to you to decide, if subclasses should be able to overwrite
the value of your instance variables. Generally they should because
that's the point of object oriented design.
I admit though, that I'm not always doing the "right thing" either ...
:-/
Andreas
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.



