Thread overview
problems with local classes
Sep 06, 2006
John Smith
Sep 10, 2006
Paul McKenzie
Sep 10, 2006
John Smith
Sep 10, 2006
Bertel Brander
Sep 10, 2006
Paul McKenzie
Sep 10, 2006
Bertel Brander
Sep 11, 2006
Jan Knepper
Sep 12, 2006
John Smith
September 06, 2006
Hi,

I have been trying to compile (using 8.42n) some code using several local classes. But I have encountered problems with the dmc-compiler. Seems like the v-tables aren't stored correctly. Which in my case means that the right function isn't called at runtime.


--- dmc_test.cpp ---
#include <iostream>

class A
{
public:
	virtual void a() = 0;
};

int main()
{
	{
		class B : public A
		{
		public:
			void a() { std::cout << "1"; }
		};
		A * a = new B;
		a->a();
		delete a;
	}
	{
		class B : public A
		{
		public:
			void a() { std::cout << "2"; }
		};
		A * a = new B;
		a->a();
		delete a;
	}

	return 0;
}
--- end of snippet ---

This code compiles nicely, but gives the result "11" instead of the expected "12". Executables compiled with Mingw 3.4.5, Visual C++ 8.0, Borland C++ 5.6.4 and Open Watcom 1.5 all produces the expected output.

 John
September 10, 2006
"John Smith" <no@spam.com> wrote in message news:edlid4$gho$1@digitaldaemon.com...
> local classes. But I have encountered problems with the dmc-compiler.

Your code produces undefined behavior.  The base class A does not have a virtual destructor, therefore doing this:

A *a = new B;
//...
delete  a;  // Error.

invalidates the rest of the code.  You cannot call "delete" on a base class pointer which is pointing to a derived class, unless the base class destructor is virtual.  If it isn't virtual, the behavior is undefined (as per ANSI C++ specification -- don't have the time to look up chapter and verse).

Change the A class to have a virtual destructor and see if the code works. Even if it doesn't work, you still need the virtual destructor for your code to really be a valid test of whether the compiler is working or not.

Paul


September 10, 2006
The delete-parts of the code was actually an after-construction, added when I posted it on the news-board (trying to avoid some irrelevant discussion.) The original code did not delete the objects, it just leaked them. Another way one is to explicitly cast it back to a B pointer in the delete-expression, and therefor fulfilling section 5.3.5.3, since the static and dynamic types are the same.

Or I could just remove the dynamic allocation all together and write.

		B b;
		A * a = &b;
		a->a();

And I am sure there are other ways of writing this without using virtual destructors. But if we were to test out your version, we could even add the virtual destructors and see that it isn't even calling the right destructor. Since the problem is most likely related to the handling of the virtual-tables.

The probability of the virtual destructors being the cause of the problem was pretty slim though, if you ask me ;) But thanks for pointing that out anyway.

  John



September 10, 2006
Paul McKenzie wrote:
> "John Smith" <no@spam.com> wrote in message
> news:edlid4$gho$1@digitaldaemon.com...
>> local classes. But I have encountered problems with the dmc-compiler.
> 
> Your code produces undefined behavior.  The base class A does not have a
> virtual destructor, therefore doing this:
> 
> A *a = new B;
> //...
> delete  a;  // Error.

Are you sure? I'm think it is perfectly legal to have a base class
without any destructor.
But if you want the destructor of the derevied class to be called
upon deletion, if deleted through a base class pointer, you need
a virtual destructor in the base class. But it is not undefined
behaviour not to have one, the behaviour is perfectly defined;
only the destructor of the base class (if any) is called.

-- 
Just another homepage:
http://damb.dk
But it's mine - Bertel
September 10, 2006
"Bertel Brander" <bertel@post4.tele.dk> wrote in message news:ee1b50$1c37$1@digitaldaemon.com...
> Are you sure? I'm think it is perfectly legal to have a base class
> without any destructor.
> But if you want the destructor of the derevied class to be called
> upon deletion, if deleted through a base class pointer, you need
> a virtual destructor in the base class. But it is not undefined
> behaviour not to have one, the behaviour is perfectly defined;
> only the destructor of the base class (if any) is called.
>

From the 1998 ANSI/ISO C++ Standard document.

Section 5.3.5 (subsection 3):

Delete:

In the first alternative (delete object), if the static type of the operand is different from its dynamic type, the static type shall be a base class of the operand's dynamic type and the static type shall have a virtual destructor *or the behavior is undefined.*

Paul


September 10, 2006
Paul McKenzie wrote:
> "Bertel Brander" <bertel@post4.tele.dk> wrote in message
> news:ee1b50$1c37$1@digitaldaemon.com...
>> Are you sure? I'm think it is perfectly legal to have a base class
>> without any destructor.
>> But if you want the destructor of the derevied class to be called
>> upon deletion, if deleted through a base class pointer, you need
>> a virtual destructor in the base class. But it is not undefined
>> behaviour not to have one, the behaviour is perfectly defined;
>> only the destructor of the base class (if any) is called.
>>
> 
> From the 1998 ANSI/ISO C++ Standard document.
> 
> Section 5.3.5 (subsection 3):
> 
> Delete:
> 
> In the first alternative (delete object), if the static type of the operand
> is different from its dynamic type, the static type shall be a base class of
> the operand's dynamic type and the static type shall have a virtual
> destructor *or the behavior is undefined.*

I think you are right.

But way does all compilers then allow you to
compile without a virtual destructor?

Just after the section you quote it says:
"In the second alternative (delete array) if the dynamic
type of the object to be deleted differs from its static
type, the behavior is undefined"

This seems strange. Why can't you delete an array of
a derived class through a pointer to a base class?

-- 
Just another homepage:
http://damb.dk
But it's mine - Bertel
September 11, 2006
Are you building with optimization on?



John Smith wrote:
> Hi,
> 
> I have been trying to compile (using 8.42n) some code using several local classes. But I have encountered problems with the dmc-compiler. Seems like the v-tables aren't stored correctly. Which in my case means that the right function isn't called at runtime.
> 
> 
> --- dmc_test.cpp ---
> #include <iostream>
> 
> class A
> {
> public:
>     virtual void a() = 0;
> };
> 
> int main()
> {
>     {
>         class B : public A
>         {
>         public:
>             void a() { std::cout << "1"; }
>         };
>         A * a = new B;
>         a->a();
>         delete a;
>     }
>     {
>         class B : public A
>         {
>         public:
>             void a() { std::cout << "2"; }
>         };
>         A * a = new B;
>         a->a();
>         delete a;
>     }
> 
>     return 0;
> }
> --- end of snippet ---
> 
> This code compiles nicely, but gives the result "11" instead of the expected "12". Executables compiled with Mingw 3.4.5, Visual C++ 8.0, Borland C++ 5.6.4 and Open Watcom 1.5 all produces the expected output.
> 
>  John

-- 
ManiaC++
Jan Knepper

But as for me and my household, we shall use Mozilla...
www.mozilla.org
September 12, 2006
No, I am not building it with any optimizations (that I know of). Just plain "dmc dmc_test.cpp". I also tried both speed (-o) and space (-o+space) optimization-flags without any success.

Jan Knepper wrote:
> Are you building with optimization on?
> 
> 
>