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

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.

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

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

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

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.

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

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