Thread overview | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
|
January 29, 2013 Adding more information to exceptions | ||||
---|---|---|---|---|
| ||||
Let's say I have some code that parses some text file: int[] numbers; foreach (lineNumber, line; lines) numbers ~= to!int(line); I would like to add some information to any exceptions thrown inside the loop's body (e.g. whatever std.conv.to may throw), in our case the line number. Previously, I "solved" this like this: foreach (lineNumber, line; lines) try numbers ~= to!int(line); catch (Exception e) throw new Exception(format("Error on line %d: %s", lineNumber, e.msg)); Of course, this has the problem that all information (except the message) from the original exception is lost. I started using the following instead, which worked: foreach (lineNumber, line; lines) try numbers ~= to!int(line); catch (Exception e) throw new Exception(format("Error on line %d", lineNumber), e); This worked, however today I noticed in the documentation that the "next" parameter is reserved for exception chaining, and should not be used by user code. So, I tried to do it the exception chaining way: foreach (lineNumber, line; lines) { scope(failure) throw new Exception(format("Error on line %d", lineNumber)); numbers ~= to!int(line); } The above doesn't work - only the exception in scope(failure) is caught. Same if I try to throw from a catch block, but interestingly works if throwing from a finally block. Q1: Is this a bug, or I just don't understand how exception chaining works? Q2: Is there a better way to achieve this (adding information to in-flight exceptions)? |
January 29, 2013 Re: Adding more information to exceptions | ||||
---|---|---|---|---|
| ||||
Posted in reply to Vladimir Panteleev | On 1/29/13, Vladimir Panteleev <vladimir@thecybershadow.net> wrote:
> foreach (lineNumber, line; lines)
> try
> numbers ~= to!int(line);
> catch (Exception e)
> throw new Exception(format("Error on line %d: %s",
> lineNumber, e.msg));
>
> Of course, this has the problem that all information (except the message) from the original exception is lost.
What I'd do is:
catch (Exception e)
{
e.msg = format("My info here...\n%s", e.msg);
throw e;
}
|
January 29, 2013 Re: Adding more information to exceptions | ||||
---|---|---|---|---|
| ||||
Posted in reply to Vladimir Panteleev | On 01/29/2013 12:32 PM, Vladimir Panteleev wrote: > I would like to add some information to any exceptions thrown inside the > loop's body (e.g. whatever std.conv.to may throw), in our case the line > number. Here is a RAII idea that takes advantage of exception chaining without directly using the 'next' parameter. It constructs a LineInfo object ready to throw in its destructor unless specifically told that it is not necessary anymore. import std.stdio; import std.string; import std.conv; void main() { auto lines = [ "42", "100", "hello" ]; int[] numbers; struct LineInfo { size_t lineNumber; bool allIsGood = false; ~this() { if (!allIsGood) { throw new Exception(format("Line number: %s", lineNumber)); } } } foreach (lineNumber, line; lines) { auto info = LineInfo(lineNumber); numbers ~= to!int(line); info.allIsGood = true; } } Ali |
January 30, 2013 Re: Adding more information to exceptions | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrej Mitrovic | On Tuesday, 29 January 2013 at 20:37:07 UTC, Andrej Mitrovic wrote:
> On 1/29/13, Vladimir Panteleev <vladimir@thecybershadow.net> wrote:
>> foreach (lineNumber, line; lines)
>> try
>> numbers ~= to!int(line);
>> catch (Exception e)
>> throw new Exception(format("Error on line %d: %s",
>> lineNumber, e.msg));
>>
>> Of course, this has the problem that all information (except the
>> message) from the original exception is lost.
>
> What I'd do is:
>
> catch (Exception e)
> {
> e.msg = format("My info here...\n%s", e.msg);
> throw e;
> }
Ah, that's clever... thanks!
|
January 30, 2013 Re: Adding more information to exceptions | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Tuesday, 29 January 2013 at 21:53:46 UTC, Ali Çehreli wrote:
> On 01/29/2013 12:32 PM, Vladimir Panteleev wrote:
>
> > I would like to add some information to any exceptions thrown
> inside the
> > loop's body (e.g. whatever std.conv.to may throw), in our
> case the line
> > number.
>
> Here is a RAII idea that takes advantage of exception chaining without directly using the 'next' parameter. It constructs a LineInfo object ready to throw in its destructor unless specifically told that it is not necessary anymore.
>
> import std.stdio;
> import std.string;
> import std.conv;
>
> void main()
> {
> auto lines = [ "42", "100", "hello" ];
>
> int[] numbers;
>
> struct LineInfo
> {
> size_t lineNumber;
> bool allIsGood = false;
>
> ~this()
> {
> if (!allIsGood) {
> throw new Exception(format("Line number: %s", lineNumber));
> }
> }
> }
>
> foreach (lineNumber, line; lines) {
> auto info = LineInfo(lineNumber);
> numbers ~= to!int(line);
> info.allIsGood = true;
> }
> }
>
> Ali
umm, so why can't using next directly be valid?
|
January 30, 2013 Re: Adding more information to exceptions | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jesse Phillips | On 01/30/2013 12:05 PM, Jesse Phillips wrote: > On Tuesday, 29 January 2013 at 21:53:46 UTC, Ali Çehreli wrote: >> Here is a RAII idea that takes advantage of exception chaining without >> directly using the 'next' parameter. > umm, so why can't using next directly be valid? The OP had quoted the documentation: http://dlang.org/phobos/object.html#.Exception "The next parameter is used internally and should be always be null when passed by user code." Ali |
January 30, 2013 Re: Adding more information to exceptions | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Wednesday, January 30, 2013 12:58:10 Ali Çehreli wrote:
> On 01/30/2013 12:05 PM, Jesse Phillips wrote:
> > On Tuesday, 29 January 2013 at 21:53:46 UTC, Ali Çehreli wrote:
> >> Here is a RAII idea that takes advantage of exception chaining without directly using the 'next' parameter.
> >
> > umm, so why can't using next directly be valid?
>
> The OP had quoted the documentation:
>
> http://dlang.org/phobos/object.html#.Exception
>
> "The next parameter is used internally and should be always be null when passed by user code."
Really? That's a weird note. I don't see any reason for it to not be used by user code. I wonder why that note is there.
- Jonathan M Davis
|
January 31, 2013 Re: Adding more information to exceptions | ||||
---|---|---|---|---|
| ||||
On 1/30/13, Jonathan M Davis <jmdavisProg@gmx.com> wrote:
>> "The next parameter is used internally and should be always be null when passed by user code."
>
> Really? That's a weird note. I don't see any reason for it to not be used by user code. I wonder why that note is there.
It should probably be changed, TDPL shows how .next is used in user-code as well.
|
February 23, 2013 Re: Adding more information to exceptions | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | Maybe I don't understand this example fully, but where is a "try" statement?
The to!int may throw...
Dňa 29. 1. 2013 22:53 Ali Çehreli wrote / napísal(a):
> On 01/29/2013 12:32 PM, Vladimir Panteleev wrote:
>
> > I would like to add some information to any exceptions thrown inside the
> > loop's body (e.g. whatever std.conv.to may throw), in our case the line
> > number.
>
> Here is a RAII idea that takes advantage of exception chaining without
> directly using the 'next' parameter. It constructs a LineInfo object
> ready to throw in its destructor unless specifically told that it is not
> necessary anymore.
>
> import std.stdio;
> import std.string;
> import std.conv;
>
> void main()
> {
> auto lines = [ "42", "100", "hello" ];
>
> int[] numbers;
>
> struct LineInfo
> {
> size_t lineNumber;
> bool allIsGood = false;
>
> ~this()
> {
> if (!allIsGood) {
> throw new Exception(format("Line number: %s",
> lineNumber));
> }
> }
> }
>
> foreach (lineNumber, line; lines) {
> auto info = LineInfo(lineNumber);
> numbers ~= to!int(line);
> info.allIsGood = true;
> }
> }
>
> Ali
>
|
February 23, 2013 Re: Adding more information to exceptions | ||||
---|---|---|---|---|
| ||||
Posted in reply to Lubos Pintes | On 02/23/2013 02:44 AM, Lubos Pintes wrote: > Maybe I don't understand this example fully, It is one way of adding information to an exception. (There are other ways.) > but where is a "try" > statement? It is not needed here because the requirement is achieved by the destructor of LineInfo. Besides, try-catch should be used only when there is something to do if an operation fails. That's one of the benefits that exceptions bring: mid-layers do not need to propagate error conditions. The code that fails to do something throws and the code that can do anything about it can catch. If you meant that main() should never leak an exception but instead print an error message to the user, I agree. But this example only demonstrated how a piece of information can be added to an exception in flight. > The to!int may throw... Indeed, it does for "hello" and the output includes both the original error and the added information: std.conv.ConvException@/usr/include/d/dmd/phobos/std/conv.d(1826): Unexpected 'h' when converting from type string to type int [...] object.Exception@deneme.d(121171): Line number: 2 [...] Ali |
Copyright © 1999-2021 by the D Language Foundation