www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - Crashes when throwing auto reference

reply Nick <Nick_member pathlink.com> writes:
This is a somewhat obscure bug, but here goes. If you throw an auto reference to
an object whose class has a destructor, the resulting program will crash. Now, I
don't know why anyone would want to do such a thing, but still it should never
just crash :)

The following example gives a segmentation fault (on linux):

class test
{
~this() {}
}

void main()
{
auto test A = new test;
throw A;
}

Nick
Jul 22 2004
next sibling parent reply John Reimer <brk_6502 NO_S_PAM.yahoo.com> writes:
On Thu, 22 Jul 2004 20:02:09 +0000, Nick wrote:

 This is a somewhat obscure bug, but here goes. If you throw an auto
 reference to an object whose class has a destructor, the resulting program
 will crash. Now, I don't know why anyone would want to do such a thing,
 but still it should never just crash :)
 
 The following example gives a segmentation fault (on linux):
 
 class test
 {
 ~this() {}
 }
 }
 void main()
 {
 auto test A = new test;
 throw A;
 }
 }
 Nick

If I'm not mistaken, I believe a segmentation fault is the expected result when you throw an exception that you do not followup with a "catch." Since you haven't specified a "catch" for the previous "throw," I think D leaves the OS to deal with the error... thus the seg fault.
Jul 22 2004
parent reply Nick <Nick_member pathlink.com> writes:
In article <pan.2004.07.22.20.36.53.94162 NO_S_PAM.yahoo.com>, John Reimer
says...
If I'm not mistaken, I believe a segmentation fault is the expected result
when you throw an exception that you do not followup with a "catch." Since
you haven't specified a "catch" for the previous "throw," I think D leaves
the OS to deal with the error... thus the seg fault.

Well, first of all, adding a try/catch statement to the given example will not stop the segfault (I've tried :-). Secondly, if you remove the ~test() destructor (or try to throw something else instead), you get a nice error message along the lines "Error: name_of_thrown_class", which is the default for uncaught exceptions (i.e. not a segfault.) Nick
Jul 22 2004
parent reply John Reimer <brk_6502 NO_S_PAM.yahoo.com> writes:
On Thu, 22 Jul 2004 21:05:03 +0000, Nick wrote:

 In article <pan.2004.07.22.20.36.53.94162 NO_S_PAM.yahoo.com>, John Reimer
 says...
If I'm not mistaken, I believe a segmentation fault is the expected
result when you throw an exception that you do not followup with a
"catch." Since you haven't specified a "catch" for the previous "throw,"
I think D leaves the OS to deal with the error... thus the seg fault.

Well, first of all, adding a try/catch statement to the given example will not stop the segfault (I've tried :-). Secondly, if you remove the ~test() destructor (or try to throw something else instead), you get a nice error message along the lines "Error: name_of_thrown_class", which is the default for uncaught exceptions (i.e. not a segfault.) Nick

Yep, apparently I was being stupid in that regard. I apologize. I tried it out and realized that the error message does get printed out if one removes the destructor. So D has a default handler obviously if one is not supplied by the programmer. Your example, then, does appear to show a bug. But I don't know why you didn't succeed when you added a try/catch statement. I was able to do it like this: // ------------------------------- import std.stdio; class test { ~this() {} } void main() { auto test A = new test; try { throw A; catch { printf("A caught\n"); } } // -------------------------------- This works... Also works with a specific catch: catch (test e). Did I do something different then you did? I'm using Gentoo Linux with linux 2.6.7 Later, John
Jul 22 2004
parent Nick <Nick_member pathlink.com> writes:
In article <pan.2004.07.22.21.22.38.79324 NO_S_PAM.yahoo.com>, John Reimer
says...

[...]
But I don't know why you didn't succeed when you added a try/catch
statement.  I was able to do it like this:

// -------------------------------

import std.stdio;

class test 
{
	~this() {}
}

void main() 
{
	auto test A = new test;
	try {
		throw A;
	catch {
		printf("A caught\n");
	}
}
// --------------------------------

This works... Also works with a specific catch: catch (test e).

Did I do something different then you did?

Oops, you are entirely correct. I just realized tried the try/catch before I made the "bare bones" example code. Originally I had put the reference/throw in a separate function, and this seems to bring the segfault back: (sorry if the spacing gets messed up, I'm posting from the digitalmars.com web interface...) class test { ~this() {} } void func() { auto test A = new test; throw new A; } void main() { try { func(); } catch { printf("A caught\n"); } } //... and the wicked witch returns! Nick
Jul 22 2004
prev sibling parent reply "Walter" <newshound digitalmars.com> writes:
"Nick" <Nick_member pathlink.com> wrote in message
news:cdp6g1$12eb$1 digitaldaemon.com...
 This is a somewhat obscure bug, but here goes. If you throw an auto

 an object whose class has a destructor, the resulting program will crash.

 don't know why anyone would want to do such a thing, but still it should

 just crash :)

 The following example gives a segmentation fault (on linux):

 class test
 {
 ~this() {}
 }

 void main()
 {
 auto test A = new test;
 throw A;
 }

The problem here is that 'auto' means 'clean up the object when it goes out of scope'. So, when the throw happens, all objects on the stack frame of main() are cleaned up, *including* A. So when the exception handler gets A, it's been deleted. Hence, the seg fault trying to access it.
Jul 23 2004
parent reply Arcane Jill <Arcane_member pathlink.com> writes:
In article <cdrl4k$2bvn$1 digitaldaemon.com>, Walter says...
The problem here is that 'auto' means 'clean up the object when it goes out
of scope'. So, when the throw happens, all objects on the stack frame of
main() are cleaned up, *including* A. So when the exception handler gets A,
it's been deleted. Hence, the seg fault trying to access it.

I suspect that Nick understood this all along. The point, though, is: shouldn't it be a compile-time error to throw an instance of an auto class? Arcane Jill
Jul 23 2004
next sibling parent "Walter" <newshound digitalmars.com> writes:
"Arcane Jill" <Arcane_member pathlink.com> wrote in message
news:cds4mh$2qs8$1 digitaldaemon.com...
 In article <cdrl4k$2bvn$1 digitaldaemon.com>, Walter says...
The problem here is that 'auto' means 'clean up the object when it goes


of scope'. So, when the throw happens, all objects on the stack frame of
main() are cleaned up, *including* A. So when the exception handler gets


it's been deleted. Hence, the seg fault trying to access it.

I suspect that Nick understood this all along. The point, though, is:

 it be a compile-time error to throw an instance of an auto class?

It's certainly illegal, though it may be possible to hide it from the compiler.
Jul 23 2004
prev sibling parent Nick <Nick_member pathlink.com> writes:
In article <cds4mh$2qs8$1 digitaldaemon.com>, Arcane Jill says...
I suspect that Nick understood this all along. The point, though, is: shouldn't
it be a compile-time error to throw an instance of an auto class?

Well, it's one of the points, anyway. ;-) Throwing an instance of an auto class should probably be treated the same as returning one, i.e. disallowed. However, I'm also wondering why all the restrictions are on auto classes, while there seems to be few restrictions on the auto references themselves (when pointing to non-auto classes.) For example, the following compiles without a problem: # // NON-auto class # class Test {} # # Test func() # { # auto Test T = new Test; # return T; # // We return an auto pointer, but the returned object will be "dead # // on arrival." # } I think this kind of buggy code should also be caught by the compiler, and produce a warning message at least. (But compiler warnings perhaps aren't implemented yet?) Nick
Jul 24 2004