views:

210

answers:

1

Hoooboy,

I've got another doozy of a memory problem.

I'm creating a Carbon (AGL) Window, in C++ and it's telling me that I'm autorelease-ing it without a pool in place.

uh... what?

I thought Carbon existed outside of the NSAutoreleasePool...

When I call glEnable(GL_TEXTURE_2D) to do some stuff, it gives me a EXC_BAD_ACCESS warning - but if the AGL Window is never getting release'd, then shouldn't it exist? Setting set objc-non-blocking-mode at (gdb) doesn't make the problem go away.

So I guess my question is WHAT IS UP WITH CARBON/COCOA/NSAutoreleasePool?

And... are there any resources for Objective-C++? Because crap like this keeps happening to me.

Thanks,

-Stephen

--- CODE ---

Test Draw Function

void Channel::frameDraw( const uint32_t frameID)
{
    eq::Channel::frameDraw( frameID );
            getWindow()->makeCurrent(false);
    glEnable(GL_TEXTURE_2D); // Throws Error Here
}

Make Current (the following code is from Equalizer API which is LGPL Eyescale)

void Window::makeCurrent( const bool useCache ) const
{
    if( useCache && getPipe()->isCurrent( this ))
        return;

    _osWindow->makeCurrent();
}

void AGLWindow::makeCurrent() const
{
    aglSetCurrentContext( _aglContext );
    AGLWindowIF::makeCurrent();

    if( _aglContext )
    {
        EQ_GL_ERROR( "After aglSetCurrentContext" );
    }
}

_aglContext is a valid memory location (i.e. not NULL) when I step through.

-S!

--- ERROR ---

859 2958110720 //Users/slate/Documents/equalizer/XCode/../lib/client/aglWindow.cpp:367   278 Created AGL context 0x4867200 shared with 0
*** __NSAutoreleaseNoPool(): Object 0x1fc4a950 of class NSCarbonWindowContentView autoreleased with no pool in place - just leaking
*** __NSAutoreleaseNoPool(): Object 0x1fc4b120 of class NSCFArray autoreleased with no pool in place - just leaking
*** __NSAutoreleaseNoPool(): Object 0x1f410f50 of class NSMutableParagraphStyle autoreleased with no pool in place - just leaking
*** __NSAutoreleaseNoPool(): Object 0x45063f0 of class NSCFDictionary autoreleased with no pool in place - just leaking
*** __NSAutoreleaseNoPool(): Object 0x2f2ed50 of class NSPathStore2 autoreleased with no pool in place - just leaking
*** __NSAutoreleaseNoPool(): Object 0x44bf380 of class NSCFData autoreleased with no pool in place - just leaking
*** __NSAutoreleaseNoPool(): Object 0xa026cb08 of class NSCFString autoreleased with no pool in place - just leaking
etc...

--- STACK ---

#0  0x9252d3f1 in __NSAutoreleaseNoPool ()
#1  0x9243a794 in _CFAutoreleasePoolAddObject ()
#2  0x9243a4aa in -[NSObject(NSObject) autorelease] ()
#3  0x9372d023 in -[NSCarbonWindow initWithCarbonWindowRef:takingOwnership:disableOrdering:] ()
#4  0x9345bdee in _cocoaAppApplicationEventHandler ()
#5  0x920f00a9 in DispatchEventToHandlers ()
#6  0x920ef370 in SendEventToEventTargetInternal ()
#7  0x920ef1cf in SendEventToEventTargetWithOptions ()
#8  0x92114e44 in SendShowHideEvent ()
#9  0x921148b1 in _ShowHideWindows ()
#10 0x92177341 in ShowWindow ()
#11 0x2a01fab0 in eq::AGLWindow::configInitAGLWindow (this=0x400d260) at /Users/slate/Documents/equalizer/XCode/../lib/client/aglWindow.cpp:541
#12 0x2a01f380 in eq::AGLWindow::configInitAGLDrawable (this=0x400d260) at /Users/slate/Documents/equalizer/XCode/../lib/client/aglWindow.cpp:393
#13 0x2a01eb32 in eq::AGLWindow::configInit (this=0x400d260) at /Users/slate/Documents/equalizer/XCode/../lib/client/aglWindow.cpp:148
#14 0x2a0a25b9 in eq::Window::configInitOSWindow (this=0x283795f0, initID=0) at /Users/slate/Documents/equalizer/XCode/../lib/client/window.cpp:435
#15 0x2a09f31b in eq::Window::configInit (this=0x283795f0, initID=0) at /Users/slate/Documents/equalizer/XCode/../lib/client/window.cpp:394
#16 0x2a0a1226 in eq::Window::_cmdConfigInit (this=0x283795f0, command=@0x4009120) at /Users/slate/Documents/equalizer/XCode/../lib/client/window.cpp:720
#17 0x2a0ae8d5 in eq::net::CommandFunc<eq::net::Dispatcher>::operator() (this=0x1ed023b4, command=@0x4009120) at commandFunc.h:50
#18 0x2a0adf4a in eq::net::Dispatcher::invokeCommand (this=0x283795f0, command=@0x4009120) at /Users/slate/Documents/equalizer/XCode/../lib/net/dispatcher.cpp:121
#19 0x2a102ec4 in eq::net::Session::_invokeObjectCommand (this=0x3061600, command=@0x4009120) at /Users/slate/Documents/equalizer/XCode/../lib/net/session.cpp:622
#20 0x2a10448c in eq::net::Session::invokeCommand (this=0x3061600, command=@0x4009120) at /Users/slate/Documents/equalizer/XCode/../lib/net/session.cpp:575
#21 0x2a0901d3 in eq::Pipe::_runThread (this=0x28377c00) at /Users/slate/Documents/equalizer/XCode/../lib/client/pipe.cpp:310
#22 0x2a0987e4 in eq::Pipe::PipeThread::run (this=0x28377a80) at pipe.h:419
#23 0x2a01a307 in eq::base::Thread::_runChild (this=0x28377a80) at /Users/slate/Documents/equalizer/XCode/../lib/base/thread.cpp:125
#24 0x2a01a48d in eq::base::Thread::runChild (arg=0x28377a80) at /Users/slate/Documents/equalizer/XCode/../lib/base/thread.cpp:101
#25 0x958aea19 in _pthread_start ()
#26 0x958ae89e in thread_start ()

Thanks for the tip on setting env NSAutoreleaseHaltNoPool = YES. Why is the the _cocoaAppApplicationEventHandler even involved here? I'm importing an AGL/Carbon plugin to a CGL/Cocoa application... is Cocoa getting all over the carbon?

According to MacWindows.h

/*
 *  [Mac]ShowWindow()
 *  
 *  Mac OS X threading:
 *    Not thread safe
 *  
 *  Availability:
 *    Mac OS X:         in version 10.0 and later in Carbon.framework [32-bit only]
 *    CarbonLib:        in CarbonLib 1.0 and later
 *    Non-Carbon CFM:   in InterfaceLib 7.1 and later
 */
#if TARGET_OS_MAC
    #define MacShowWindow ShowWindow
#endif
extern void 
MacShowWindow(WindowRef window)                               AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER;

It should be just a straight-up Carbon call... so I don't know why Cocoa is trying to manage it. It just seems so odd that it doesn't work here - but it works fine in another project. All the config settings, etc. are the same between the projects, so I just have a hard time understanding why this is a problem.

-S!

+1  A: 

Ugh,

So if anyone else is looking for a similar answer, I'll post what I've found.

The answer is that the Carbon Window is being generated as part of a Cocoa Plugin for a Cocoa app. Hence, the Carbon Window needs to follow all the rules for memory management in both Carbon and Cocoa. Hence why a reference to NSCarbonWindow gets created and tries to add it to the autorelease pool.

1) A solution would be to not use Carbon (duh) since Apple is deprecating it faster that Adobe. :P

2) Another solution would be to manually add the Carbon Window and manage the memory properly. Since I'm using a Carbon API I can't really do that.

3) The third solution would be to break the programs apart. Use the Carbon API in a separate .app than the Cocoa Plugin. This is what I'll have to do, and just pass info via MachPorts or something between the two apps.

Hope this helps somebody else. Mt personal suggestion is, of course, #1.

-Stephen

Stephen Furlani
If anything is happening inside a Cocoa plug-in, there must be an autorelease pool in place. It’s not immediately obvious whose responsibility that is in this particular case, though.
Ahruman
Yeah, there is an autorelease pool in place, but the C++/Carbon code exists in it's own thread or something that doesn't have access to the Autorelease pool created in main.m.For example, when I load some data with CoreData I have to bracket it in another Autorelease Pool - it won't latch onto the main app's pool. I can't edit the Carbon API, so I'm stuck doing something else.
Stephen Furlani