gnustep-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Memory leaks galore!


From: Ivan Vučica
Subject: Re: Memory leaks galore!
Date: Wed, 20 Feb 2013 22:54:42 +0100


On 20. 2. 2013., at 20:50, Jamie Ramone <address@hidden> wrote:

That is my understanding of free() too. The problem is not with freeing one massive 1gb block. But imagine freeing 1gb of SMALL objects. If -dealloc is more complex and references ivars, you need to swap them in, free subobjects, stuff like that.

Oh, OK, I see what you mean now. Yes, that case is an obvious swap-monsoon. However, the proper way to deal with that problem is not causing it in the first place. Plus, main memory is progressively abundant. It gets harder and harder to use up all the memory so as to cause even a single swap, at least by the data structures themselves. I don't even have a swap partition, what with having 8 GB and all. I don't know, it seems like a not very common case.

GNUstep runs on a large amount of systems, and in fact, there are additional implementations of OPENSTEP/Cocoa targeting embedded systems because authors perceive GNUstep is large and slow. I don't know -- someone may have a use case. Sure, it's rare, but GNUstep doesn't really shy away from rare configurations or use cases :-)



There is probably some way of telling Valgrind to ignore certain leaks, right?

I'll check the documentation but I don't think that's possible. Valgrind checks for alloc/free balance. While you can change the level of verbosity, I don't think it's possible to get it to filter (what it sees as) leaks. But like I said, I have to check the documentation just to be sure.

<smartass>
You could always write a script that filters out these warnings. 
</smartass>

;)

 
The only case where you want to dealloc stuff is where you do deinitialization of network connection and similar things in -(void)dealloc, and yesterday I ran into Apple recommendation that in clean code you don't really want to do that in -(void)dealloc. Or should avoid it as much as possible. I'm cargo-culting here; it sounds reasonable, but I don't really have anything more than that.

I know, that's why I use release ;-)

You override -release to release resources at object's end-of-life? :-S

No, I release an object once I'm done using it making use of the reference count mechanism. I'm surprised you never heard of it, it's been around for decades :P

<3 sarcasm. :-)

But the reference count mechanism  guarantees that -dealloc will eventually be called, at least in theory, where we don't have this leave-it-to-the-os hack. Which is why I have implementations of -dealloc in my objects.

That's precisely how I do things, but what I'm talking about is this.
And that's in context of "the only thing that would **require** calling -dealloc (by, of course, calling -release) during program shutdown is network connections and similar things".

And the Word of God right now is -- "don't use -dealloc to do that, it's error prone, and you don't really know how the object graph will be torn down".

Quoting:

<Apple>
Don’t Use dealloc to Manage Scarce Resources

You should typically not manage scarce resources such as file descriptors, network connections, and buffers or caches in a dealloc method. In particular, you should not design classes so that dealloc will be invoked when you think it will be invoked. Invocation of dealloc might be delayed or sidestepped, either because of a bug or because of application tear-down.

Instead, if you have a class whose instances manage scarce resources, you should design your application such that you know when you no longer need the resources and can then tell the instance to “clean up” at that point. You would typically then release the instance, and dealloc would follow, but you will not suffer additional problems if it does not.

Problems may arise if you try to piggy-back resource management on top of dealloc. For example:

• Order dependencies on object graph tear-down.
The object graph tear-down mechanism is inherently non-ordered. Although you might typically expect—and get—a particular order, you are introducing fragility. If an object is unexpectedly autoreleased rather than released for example, the tear-down order may change, which may lead to unexpected results.

• Non-reclamation of scarce resources.
Memory leaks are bugs that should be fixed, but they are generally not immediately fatal. If scarce resources are not released when you expect them to be released, however, you may run into more serious problems. If your application runs out of file descriptors, for example, the user may not be able to save data.

• Cleanup logic being executed on the wrong thread.
If an object is autoreleased at an unexpected time, it will be deallocated on whatever thread’s autorelease pool block it happens to be in. This can easily be fatal for resources that should only be touched from one thread.
</Apple>

So -- they basically recommend "clean up system resources in a separate method, don't piggy-back on -dealloc".

 
Oh, BTW, about that macro, do you mean redefine it in my code or recompile GNUstep-base?

Recompile, of course :-)

The "let's-call-it-problematic" code is in implementation file, in GSPrivateBuildStrings(), and it gets compiled into the library. By just changing the macro in your code, what it expands into in GSPrivateBuildStrings() didn't actually change.

By the way, can you try getting some valgrind info about the 390kb that is not-deallocated-but-is-still-reachable-so-we-didn't-print-it-out? 


reply via email to

[Prev in Thread] Current Thread [Next in Thread]