Thread overview
Crashes when throwing auto reference
Jul 22, 2004
Nick
Jul 22, 2004
John Reimer
Jul 22, 2004
Nick
Jul 22, 2004
John Reimer
Jul 22, 2004
Nick
Jul 23, 2004
Walter
Jul 23, 2004
Arcane Jill
Jul 24, 2004
Walter
Jul 24, 2004
Nick
July 22, 2004
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


July 22, 2004
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.


July 22, 2004
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


July 22, 2004
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





July 22, 2004
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


July 23, 2004
"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
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;
> }

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.


July 23, 2004
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


July 24, 2004
"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
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?

It's certainly illegal, though it may be possible to hide it from the compiler.


July 24, 2004
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