> On 19 Dec 2017, at 18:57, Lobron, David <[email protected]> wrote: > > Hey David- > > I've now got a very pruned-down program that reproduces the bug. However, > that program still uses NSException, NSAutoreleasePool, and the > NS_DURING/HANDLER/ENDHANDLER macros. I've tried replacing these with plain > @try/@catch and @throw in order to depend only on libobjc2, but so far the > latter code hasn't reproduced the bug. For example, here is some code from > my minimal code that reproduces the bug: > > @interface MinRep2 : NSObject { > } > - (void)poke; > @end > @implementation MinRep2 > - (void)poke { > NSAutoreleasePool *pool = [NSAutoreleasePool new]; > NS_DURING { > [NSException raise:@"foo" format:@"bar"]; > } NS_HANDLER { > [localException retain]; > [pool release]; > [[localException autorelease] raise]; > } NS_ENDHANDLER > [pool release]; > } > @end > > I tried to translate this into code that depends only on libobjc2 as follows > (this inherits the Test class in the libobjc2 Test directory): > > @interface MinRep2 : Test { > } > - (void)poke; > @end > @implementation MinRep2 > - (void)poke { > id e1; > @try { > @throw e1; > } @catch (id x) { > [x retain]; > [x autorelease]; > @throw x; > } > } > @end > > Am I doing this translation approximately the right way? The "raise" method > in the gnustep-base NSException class does a lot of things, and so it's > likely that my call to @throw above might be missing something essential to > coercing the ObjC exceptions to and from a C++ one.
This looks mostly correct, though you have removed the autorelease pool calls (objc_autoreleasePoolPush() / objc_autoreleasePoolPop()). The big difference is that this looks as if it might be rethrowing, whereas your other code is definitely calling another function that is throwing the object again (in a different exception object). This is a bit more interesting, because this is the case where you’re in a catch block, but now you’re throwing another exception out of it. This logic might be incorrect in the runtime, because I don’t think it’s well tested. When we unwind through this stack frame, if it’s in a C++ compilation unit, then we should be calling objc_end_catch() in the cleanup, which should be deallocating the first exception, decrementing the reference count of the object, and then resuming throwing the other object. It’s entirely possible that there’s a bug somewhere there... David _______________________________________________ Discuss-gnustep mailing list [email protected] https://lists.gnu.org/mailman/listinfo/discuss-gnustep
