Cup level is: 10But my result which compiled with GNUstep is following:
Cup level is: 20
Cup level is: 30
Cup level is: 40
CupWarningException: Cup level is: 50
CupWarningException: Cup level is: 60
CupWarningException: Cup level is: 70
CupWarningException: Cup level is: 80
CupWarningException: Cup level is: 90
CupWarningException: Cup level is: 100
CupOverflowException: Cup level is: 110
CupUnderflowException: The level is below 0
> Does it mean the exception implementation of GNUstep is not complete as well as Apple runtime?
There are two implementations of exception handling for use with GNUstep. One is the old NeXT-style implementation, using setjmp()/longjmp(), which is slow, unsafe, and needs to die a quick and peaceful death. You may only use this with the NS_DURING family of macros.
The other is DWARF zero-cost exception handling, which uses the same mechanism as the newer GNU C++ ABI and as Apple's modern runtime. This uses asynchronous unwinding tables and allows cleanup in intervening stack frames irrespective of their language. This ought to be the default, but I'm not sure if it is.
The catch is that you can not mix the two mechanisms, or you get some problems. If you are using the @throw stuff, then you are using the DWARF ABI, but if your GNUstep is using the setjmp() mechanism then you may experience problems.
Note that there are several errors and serious omissions in the explanation of the code in the page that you linked to - I haven't read the code example in detail, but if it's written by someone with the same little understanding of the EH mechanism as displayed by the author of the page, then I wouldn't be surprised if it's buggy.
David
-- Sent from my brain
In that case, you should use NS_DURING/NS_HANDLER/NS_ENDHANDLER. The syntax and internals
are not slick but they work and have been in use for ages. ;-)
Thanks
-----Original Message-----
From: "Shuduo Sang" <sangs...@gmail.com>
Sent: Friday, 4 June, 2010 13:18
To: discuss...@gnu.org
Subject: does GNUstep support exception as well as apple implementation?
_______________________________________________
Discuss-gnustep mailing list
Discuss...@gnu.org
http://lists.gnu.org/mailman/listinfo/discuss-gnustep
Hi folks,
I am studying objc these days.I decide to use GNUstep as development env
since I am familiar with Linux. I use following link as my tutorial.
http://www.otierney.net/objective-c.html.en#exceptions
But I see the example code execution result is different to that article.
The expected result should be:
Cup level is: 10
Cup level is: 20
Cup level is: 30
Cup level is: 40
CupWarningException: Cup level is: 50
CupWarningException: Cup level is: 60
CupWarningException: Cup level is: 70
CupWarningException: Cup level is: 80
CupWarningException: Cup level is: 90
CupWarningException: Cup level is: 100
CupOverflowException: Cup level is: 110
CupUnderflowException: The level is below 0
But my result which compiled with GNUstep is following:
Cup level is: 10
Cup level is: 20
Cup level is: 30
Cup level is: 40
Aborted
Does it mean the exception implementation of GNUstep is not complete as well
as Apple runtime?
Thanks,
Shuduo
Am 04.06.2010 um 15:30 schrieb David Chisnall:
> On 4 Jun 2010, at 12:18, Shuduo Sang wrote:
>
>> Does it mean the exception implementation of GNUstep is not
>> complete as well as Apple runtime?
>
>
> There are two implementations of exception handling for use with
> GNUstep. One is the old NeXT-style implementation, using setjmp()/
> longjmp(), which is slow, unsafe, and needs to die a quick and
> peaceful death. You may only use this with the NS_DURING family of
> macros.
Can you explain that a little?
My view is:
Exceptions are exceptions and should never occur in normal operation.
So it does not matter that they are slow when they got rised (is this
currect English?). Or you have a fundamental design problem. So, IMHO
the only "cost" is the setjmp() hidden by the NS_DURING macro which
AFAIK fills an array with some pointers and values.
And what is specifically unsafe with using them? They have been in use
for 20 years now.
BR,
Nikolaus
On 4 Jun 2010, at 16:04, Dr. H. Nikolaus Schaller wrote:
> Hi David,
>
> Am 04.06.2010 um 15:30 schrieb David Chisnall:
>
>> On 4 Jun 2010, at 12:18, Shuduo Sang wrote:
>>
>>> Does it mean the exception implementation of GNUstep is not complete as well as Apple runtime?
>>
>>
>> There are two implementations of exception handling for use with GNUstep. One is the old NeXT-style implementation, using setjmp()/longjmp(), which is slow, unsafe, and needs to die a quick and peaceful death. You may only use this with the NS_DURING family of macros.
>
> Can you explain that a little?
>
> My view is:
>
> Exceptions are exceptions and should never occur in normal operation. So it does not matter that they are slow when they got rised (is this currect English?). Or you have a fundamental design problem.
Absolutely - they're called exceptions because they should happen in exceptional circumstances.
> So, IMHO the only "cost" is the setjmp() hidden by the NS_DURING macro which AFAIK fills an array with some pointers and values.
setjmp() is required to dump all of the registers in the CPU into a buffer. This is not hugely expensive, but is a significantly greater cost than nothing. It's typically at least 16 or so instructions (including stores from FPU registers - more if you have a vector unit) every time that you go over an NS_DURING macro, even when no exception is thrown. This costs memory bandwidth, d-cache usage to store the buffer, and i-cache usage to store the string of instructions required for saving the CPU state.
In contrast, the zero-cost exceptions cost nothing unless they are actually used. Entering an @try block does not involve executing any instructions. The only cost is a slight increase in the size of the binary, but because the unwinding tables are only used during unwinding they do not need to be loaded into memory unless an exception is thrown.
When an exception is thrown with the zero-cost mechanism, the unwind library parses these tables and calls the correct personality function for every frame on the stack, asking it if it has cleanup code or if it has a handler. If a handler is not found, the unwind library just aborts. If there is a handler, then the intervening unwind code is called and then the handler.
> And what is specifically unsafe with using them? They have been in use for 20 years now.
They are unsafe because they do not do anything like graceful unwinding of the stack. They just load a set of CPU registers from a buffer. This gives none of the intervening stack frames a chance to call cleanup code. For example, you can't release a lock or deallocate on-heap temporaries if an exception is thrown over your stack frame.
If you mix Objective-C and C++ this is especially bad. If you have C++ stack frames, they will typically involve things like destructor calls that happen automatically when C++ on-stack variables go out of scope. This also happens with C code if you use __attribute__((cleanup)).
There is a reason why the NeXT documentation recommends against using exceptions for anything other than printing a message and aborting - they leave your program in an undefined state. Using setjmp()/longjmp() instructions is an absolutely terrible idea and should not be done unless there are absolutely no other options.
Note: Windows' SEH also involves a cost for entering and leaving exception blocks, but does not have the other problems of setjmp() exceptions.
David
he said: "I am studying objc these days".
I am afraid your answer is way above his level for now.
@Shuduo:
So I am throwing in this link (not an exception ;-)) to provide some
basics:
http://developer.apple.com/mac/library/documentation/cocoa/conceptual/
Exceptions/Tasks/HandlingExceptions.html
Here especially compare the paragraphs "Handling Exceptions Using
Compiler Directives" (this is what you tried and the so called
"modern" form) vs. "Handling Exceptions Using Macros" (scroll down
that page for this, this is the "old" or "NeXT-style" implementation)
To explain what you experienced: You most likely have a GNU-ObjC-
runtime version which only supports the old style exceptions, ask
David for how to get the new runtime to work.
regards,
Lars
Am 04.06.2010 um 15:30 schrieb David Chisnall:
> On 4 Jun 2010, at 12:18, Shuduo Sang wrote:
>
>> Does it mean the exception implementation of GNUstep is not
>> complete as well as Apple runtime?
>
>
> There are two implementations of exception handling for use with
> GNUstep. One is the old NeXT-style implementation, using setjmp()/
> longjmp(), which is slow, unsafe, and needs to die a quick and
> peaceful death. You may only use this with the NS_DURING family of
> macros.
>
> The other is DWARF zero-cost exception handling, which uses the
> same mechanism as the newer GNU C++ ABI and as Apple's modern
> runtime. This uses asynchronous unwinding tables and allows
> cleanup in intervening stack frames irrespective of their
> language. This ought to be the default, but I'm not sure if it is.
>
> The catch is that you can not mix the two mechanisms, or you get
> some problems. If you are using the @throw stuff, then you are
> using the DWARF ABI, but if your GNUstep is using the setjmp()
> mechanism then you may experience problems.
>
> Note that there are several errors and serious omissions in the
> explanation of the code in the page that you linked to - I haven't
> read the code example in detail, but if it's written by someone
> with the same little understanding of the EH mechanism as displayed
> by the author of the page, then I wouldn't be surprised if it's buggy.
>
> David
>
> -- Sent from my brain
>
>
> Hi Nikolaus,
>
> On 4 Jun 2010, at 16:04, Dr. H. Nikolaus Schaller wrote:
>
>> Hi David,
>>
>> Am 04.06.2010 um 15:30 schrieb David Chisnall:
>>
>>> On 4 Jun 2010, at 12:18, Shuduo Sang wrote:
>>>
>>>> Does it mean the exception implementation of GNUstep is not
>>>> complete as well as Apple runtime?
>>>
>>>
>>> There are two implementations of exception handling for use with
>>> GNUstep. One is the old NeXT-style implementation, using setjmp()/
>>> longjmp(), which is slow, unsafe, and needs to die a quick and
>>> peaceful death. You may only use this with the NS_DURING family
>>> of macros.
>>
>> Can you explain that a little?
>>
>> My view is:
>>
>> Exceptions are exceptions and should never occur in normal
>> operation. So it does not matter that they are slow when they got
>> rised (is this currect English?). Or you have a fundamental design
>> problem.
>
> Absolutely - they're called exceptions because they should happen in
> exceptional circumstances.
>
>> So, IMHO the only "cost" is the setjmp() hidden by the NS_DURING
>> macro which AFAIK fills an array with some pointers and values.
>
> setjmp() is required to dump all of the registers in the CPU into a
> buffer. This is not hugely expensive, but is a significantly
> greater cost than nothing. It's typically at least 16 or so
> instructions (including stores from FPU registers - more if you have
> a vector unit) every time that you go over an NS_DURING macro, even
> when no exception is thrown. This costs memory bandwidth, d-cache
> usage to store the buffer, and i-cache usage to store the string of
> instructions required for saving the CPU state.
Well, I usually follow a fix-if-you-have-a-problem strategy. So
reducing potentially 16 instructions doesn't make it worth changing
everything in language, compiler, runtime, code.
> In contrast, the zero-cost exceptions cost nothing unless they are
> actually used. Entering an @try block does not involve executing
> any instructions. The only cost is a slight increase in the size of
> the binary, but because the unwinding tables are only used during
> unwinding they do not need to be loaded into memory unless an
> exception is thrown.
>
> When an exception is thrown with the zero-cost mechanism, the unwind
> library parses these tables and calls the correct personality
> function for every frame on the stack, asking it if it has cleanup
> code or if it has a handler. If a handler is not found, the unwind
> library just aborts. If there is a handler, then the intervening
> unwind code is called and then the handler.
Ok. This makes handling exceptions slower.
>
>> And what is specifically unsafe with using them? They have been in
>> use for 20 years now.
>
> They are unsafe because they do not do anything like graceful
> unwinding of the stack. They just load a set of CPU registers from
> a buffer. This gives none of the intervening stack frames a chance
> to call cleanup code. For example, you can't release a lock or
> deallocate on-heap temporaries if an exception is thrown over your
> stack frame.
Ok. If you take care of it, it is fine. You just have to make sure tha
t you double-wrap potential situations. E.g.:
NS_DURING
lock=[[NSLock] alloc] init];
... code that may raise an exception
[lock unlock];
NS_HANDLER
[lock unlock]; // explicit cleanup code
[localException raise]; // re-raise after cleanup (i.e. unwind into
next stack frame level)
NS_ENDHANDLER
The only thing is that you have to trust that code you don't have
control over is following such a cleanup pattern. With the try/catch
pattern, probability is lower but it does not prevent programmers to
forget the cleanup code that is required. So I would conclude it is
not inherently more unsafe than the zero-cost mechanism.
>
> If you mix Objective-C and C++ this is especially bad. If you have C
> ++ stack frames, they will typically involve things like destructor
> calls that happen automatically when C++ on-stack variables go out
> of scope. This also happens with C code if you use
> __attribute__((cleanup)).
Well, if I had to choose I would more move Obj-C++ to a peaceful
death... It leads to bloatware in compilers, debuggers and language
concepts. The only Obj-C++ project I had to develop for a customer was
a nightmare in debugging. If the client hadn't insisted on using Obj-C+
+ I would have rewritten and debugged all the C++ libs he did want to
reuse in much less time.
> There is a reason why the NeXT documentation recommends against
> using exceptions for anything other than printing a message and
> aborting - they leave your program in an undefined state. Using
> setjmp()/longjmp() instructions is an absolutely terrible idea and
> should not be done unless there are absolutely no other options.
Unless you do it in the way as I have indicated above.
> Note: Windows' SEH also involves a cost for entering and leaving
> exception blocks, but does not have the other problems of setjmp()
> exceptions.
Nevertheless, I understand that the try/catch/finally pattern
inherited from JAVA is easier to understand and to maintain.
BR,
Nikolaus
David,
he said: "I am studying objc these days".
I am afraid your answer is way above his level for now.
@Shuduo:
So I am throwing in this link (not an exception ;-)) to provide some basics:
http://developer.apple.com/mac/library/documentation/cocoa/conceptual/Exceptions/Tasks/HandlingExceptions.html
Here especially compare the paragraphs "Handling Exceptions Using Compiler Directives" (this is what you tried and the so called "modern" form) vs. "Handling Exceptions Using Macros" (scroll down that page for this, this is the "old" or "NeXT-style" implementation)
To explain what you experienced: You most likely have a GNU-ObjC-runtime version which only supports the old style exceptions, ask David for how to get the new runtime to work.
regards,
Lars
Am 04.06.2010 um 15:30 schrieb David Chisnall:
On 4 Jun 2010, at 12:18, Shuduo Sang wrote:
Does it mean the exception implementation of GNUstep is not complete as well as Apple runtime?
There are two implementations of exception handling for use with GNUstep. One is the old NeXT-style implementation, using setjmp()/longjmp(), which is slow, unsafe, and needs to die a quick and peaceful death. You may only use this with the NS_DURING family of macros.
The other is DWARF zero-cost exception handling, which uses the same mechanism as the newer GNU C++ ABI and as Apple's modern runtime. This uses asynchronous unwinding tables and allows cleanup in intervening stack frames irrespective of their language. This ought to be the default, but I'm not sure if it is.
The catch is that you can not mix the two mechanisms, or you get some problems. If you are using the @throw stuff, then you are using the DWARF ABI, but if your GNUstep is using the setjmp() mechanism then you may experience problems.
Note that there are several errors and serious omissions in the explanation of the code in the page that you linked to - I haven't read the code example in detail, but if it's written by someone with the same little understanding of the EH mechanism as displayed by the author of the page, then I wouldn't be surprised if it's buggy.
David
-- Sent from my brain
Yes, because I doubted that it is more unsafe.
And a working and mature concept was augmented by another one which
has IMHO only marginal improvements - and some (also minor) drawbacks
(e.g. requiring a higher minimum version number of the compilers).
David,
he said: "I am studying objc these days".
I am afraid your answer is way above his level for now.
@Shuduo:
So I am throwing in this link (not an exception ;-)) to provide some basics:
http://developer.apple.com/mac/library/documentation/cocoa/conceptual/Exceptions/Tasks/HandlingExceptions.html
Here especially compare the paragraphs "Handling Exceptions Using Compiler Directives" (this is what you tried and the so called "modern" form) vs. "Handling Exceptions Using Macros" (scroll down that page for this, this is the "old" or "NeXT-style" implementation)
To explain what you experienced: You most likely have a GNU-ObjC-runtime version which only supports the old style exceptions, ask David for how to get the new runtime to work.