Re: Leaked NSString from class_getInstanceMethod

Christiaan Hofman <[email protected]> Sat, 23 Jul 2011 19:14:36 +0200
Newsgroups gmane.comp.macosx.devel
Message-ID <[email protected]>
On Jul 23, 2011, at 17:36, Kyle Sluder wrote:

> On Sat, Jul 23, 2011 at 5:29 AM, Christiaan Hofman =
<[email protected]> wrote:
>> When I use the function class_getInstanceMethod() in +load in a =
PDFDocument category, I get the following message in the console log:
>>=20
>> *** __NSAutoreleaseNoPool(): Object 0x100404b30 of class NSCFString =
autoreleased with no pool in place - just leaking
>>=20
>> I really don't do anything else than what I said (at least in a test, =
the actual code I would like to have of course does a bit more, but =
that's not relevant).
>>=20
>> this makes absolutely no sense to me. The function is a runtime =
method, so it should never even use any Cocoa itself. So what NSCFString =
could this actually be? It also does not happen when I do the same in =
categories on other classes, including PDFKit classes. Anyone has an =
idea?
>=20
> Not entirely sure why a runtime method can't use an NSAutoreleasePool.
> It sounds like it would be nice if it didn't, but I don't think
> there's any such guarantee.
>=20

I don't think the runtime (function, not method) should ever use any =
Cocoa methods and objects, because the runtime is called before the =
Cocoa classes are properly setup and initialize. Calling any Cocoa from =
a runtime method will almost certainly lead to problems, because the =
whole setup of Cocoa itself will be mixed up. So I disagree that there's =
no such guarantee. Quite to the contrary, if such a guarantee would not =
exist, than logically the whole runtime would be internally inconsistent =
and buggy by design. I cannot believe that would be the case.

> The last comment on this blog post from Bill Bumgarner implies that
> this is a known shortcoming of +load:
> =
http://www.friday.com/bbum/2009/09/06/iniailize-can-be-executed-multiple-t=
imes-load-not-so-much/
>=20

I think you don't understand the problem. It's not the fact that there's =
no autorelease pool present, I know that. The problem is that an =
autorelease pool would be needed in the first place. I am not using =
Cocoa, and therefore I never should need an autorelease pool.

> That leads us to the question: why are you using +load in the first
> place? As bbum says, it's a very fragile time. This method is
> executing during static constructor time, before the C runtime has
> even called your main(). Can you defer your work to +initialize?
>=20
> --Kyle Sluder

+initialize is defined for a class, while +load is defined both for a =
class and/or a category. More precisely, for each class only one version =
of +initialize is called (once or more than once), while *all* variants =
of +load defined in *all* categories are called by the runtime. As I am =
talking about a category, +initialize does not apply, as it cannot be =
(safely) defined (and called) in a category.

And I am using functions rather than Cocoa precisely because I know it's =
fragile. I do know very well that you simply cannot use Cocoa in +load, =
that's always dangerous, because +load can be called before Cocoa has =
been fully set up and initialized. So also using my own autorelease pool =
in +load is dangerous, so I cannot even do what this comment suggests.

What is also strange is that when I define a local autorelease pool, its =
-addObject: method is never called.

Something very strange and buggy is going on. I tend to think now that =
it's really the log that's wrong rather than what it says.

Christiaan