On 18/01/2025 08:57, Daniel Santos wrote:
Hi,

I am attaching a tgz with a small example project. It has a Makefile (the 
Makefile is called Makefile.gnustep and there should be a symlink to it)
the executable is written into a bin subdirectory. The code is just a class 
that creates a string and exits.

I ran it with valgrind —leak-check=yes and am attaching the output from that.
 From what I see in the output, the only case that resembles what I saw when I 
ran valgrind on my library is a leak in a [NSString initWithFormat] call 
(Client.m:15) )which is the one that calls malloc in gnustep library.

There is a lot of other output that I don’t know if they are real leaks or not, 
maybe someone can shed some light on it as I don’t understand them.

Thanks

Please excuse stuff you already know ... I decided to take this as an
opportunity to add an example to the GNUstep-base programming manual, so
I aimed it at a beginner. I hope it helps though.

Looking at the code:

#import "Client.h" @implementation Client - (void) executeCallSequence

{ NSString *str = [NSString stringWithFormat: @"one little string :
%d\n", 100]; const char *strCharPtr = [str cString]; } @end int main(int
argv, char** argc)

{ Client *client = [[Client alloc] init];

[[NSAutoreleasePool alloc] init]; [client executeCallSequence];

return 0;

} So, what do we expect this to do?

Firstly this creates a Client instance, owned by the main function. This
is because +alloc returns an instance owned by the caller, and -init
consumes its receiver and returns an instance owned by the caller, so
the alloc/init sequence produces an instance owned by the main function.

Next, creates/enters an autorelease pool, owned by the main function.

Next, executes the method:

Creates an NSString which is NOT owned by the method.

The +stringWithFormat: method creates a new inmstance and adds it to the
current autorelease pool before returning it.

Creates a C string, which is NOT owned by the method.

A non-object return value can't be retained or released, but it conforms
to the convention that the memory is not owned by the caller, so the
caller need not free it. The -cString method is free to manage that
however it likes (for instance it might return a pointer to some
internal memory which exists until the NSString object is deallocated),
but typically what's returned is a pointer to memory inside some other
object which has been autoreleased.

A simple look at the basic retain count and autorelease rules would say
that all the memory is leaked (because the program contains no call to
release anything), but there's a bit of behind the scenes magic: when a
thread exits it releases all the autorelease pools created in it which
were not already released.

So when you consider that, you can see that the autorelease pool is
deallocated so the memory of the pool is actually freed, and the memory
of the NSString and C-String inside it are therefore also freed.

This leaves us with the memory of the Client object being leaked.
However, the idea that any unfreed memory is a leak is too simplistic
(leak checkers would be useless if they reported so much) so the leak
checker only reports some unfreed memory ... stuff that can't be reached
from various standard routes. The main case is that anything pointed to
by global or static variables is not considered leaked, but also
anything pointed to by a variable in the main() function is not
considered leaked. This is why the Client instance is not reported.

So, if automated cleanup at exit covers the strings and the Client
instance is not counted as a leak, what does get logged?

In your logs I see leaks reported for the runtime functions
class_addMethod and__objc_exec_class. These are old and minor runtime
library bugs. If you update to using the latest runtime library from the
git repository, these leak reports should go away.

The other logs look like leftovers from setting up the main thread;
something normally counted as still reachable (and therefore not
reported as leaks) on program exit. They don't show up in LeakSanitizer,
but I guess valgrind has different rules about what it counts as leaks.


Reply via email to