Were you ever convinced that you'd found a compiler bug...

Started by
11 comments, last by Succinct 22 years, 8 months ago
... only to later find out, usually in front of others, that it was more your lack of command of the language? I''m abstracting the Ogl Client/Server model. In my model, clients and classes derived from client connect to the gl "server". Well, the client portion of the classes had the sole responsiblity of delegating connection, disconnection, uploading data to the hardware, and unloading said data. Being that it was responsible for these, when any client was destroyed, the client portion of it was suppossed to make sure the client was disconnected and that it had successfully and completely unloaded itself from the hardware. Heh, unload is a virtual function. It was being called in the client base''s destructor... For those of you who know what''s wrong with this, a very basic c++ programming paradigm error, I give a tip of the hat. Funny stuff to us closet nerds, I''ll tell ya! Thank you for your bandwidth. -- Succinct ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- Succinct(Don't listen to me)
Advertisement
actually several times - of course, since I am testing a compiler, It turned out to be real bugs quite often

You know, I never wanted to be a programmer...

Alexandre Moura
It''s not a bug or paradigm error, but it''s just the way C++ virtual functions work. Here''s how I think it goes: virtual functions are accessed through an implicit table (called the vtable) that contains all the virtual functions of the class inheritance tree. When creating and object, the vtable hasn''t been fully constructed, so the wrong virtual function gets called. And that''s why you shouldn''t call virtual functions in the constructor. Same goes for the destructor, but there it''s because the vtable is being cleaned up when destroying the object.

Perhaps an example:
  #include <iostream>using namespace std;class A{public:  A() { func(); }  virtual ~A() { func2(); }  virtual void func() { cout << "A::func()" << endl; }  virtual void func2() { cout << "A::func2()" << endl; }};class B : public A{public:  B() : A() {}  virtual void func() { cout << "B::func()" << endl; }  virtual void func2() { cout << "B::func2()" << endl; }};void main(){  A *a = new B();  delete a;}  


Now you''d expect that the output of this code should be:

B::func()
B::func2()


But it''s not, and that''s because of the vtable stuff. So the actual ouput is:

A::func()
A::func2()


You have no idea how long I''ve searched for bugs in my programs, before I discovered this . Other languages like Java handle this in a much more consequent manner: there the correct virtual function gets called, both in the constructor and the destructor. But I still like C++ better .

Dormeur
Wout "Dormeur" NeirynckThe Delta Quadrant Development Page
Correct!

Being that unload is called in the client''s destructor, the derived portions of the object have been destroyed, and their destructors have already been called.

Worst of all, being that unload is pure virtual at the client base level, I get a system error stating "pure virtual function called".

arrgh.

That''s what I get for being a slow-head and not RTGDFM.

-- Succinct
-- Succinct(Don't listen to me)
I just wanted to state that it is valid for only the construtor and the destructor. If you do that any other function, the right virtual function will be called.


It act like this for the constructor and the destructor because of the order of creation :

when you create a derived class, this happens :

1.Base class constructor is called.
2.Derived class constructor is called.

when you destroy it :

1. Derived class is destroyed.
2. Base class is destroyed

look at this example and you will understand why constructor and destructor use only the functions at class level :

  class Base{ public:        Base()        {           DoStuff();        }        virtual void DoStuff() = 0;        virtual ~Base()        {            DoStuff();        }};class Derived : public Base{ public:     Derived()      {        myData = new int[40];     }     void DoStuff()     {          for( int i = 0; i < 40; ++i )          {              myData[i] = i;          }     }           ~Derived() { delete myData;}private:    int* myData;};       


See, DoStuff will crap out if called from the constructor or destructor because DoStuff depends on some member attribute.

I don''t see how Java can handle it differently and not cause crashes.
Yes, I wonder how java pulls that off...
-- Succinct(Don't listen to me)
Here''s one I haven''t solved. In VC6 I am unable to declare an array of ints called scr1...

void func ()
{
int scr1[4];

...
}

I get: error C2143: syntax error : missing '';'' before ''constant''

If I change the 1 to another number it works. Either the symbol "scr1" is defined elsewhere, or there''s some internal keyword that I am colliding with. Any thoughts?
quote:Original post by Mr Ekted
Here''s one I haven''t solved. In VC6 I am unable to declare an array of ints called scr1...

void func ()
{
int scr1[4];

...
}

I get: error C2143: syntax error : missing '';'' before ''constant''

If I change the 1 to another number it works. Either the symbol "scr1" is defined elsewhere, or there''s some internal keyword that I am colliding with. Any thoughts?



I just tried it, including nothing in the file and it compile ok. So there is probably a macro called scr1 from one of your include.
I don''t know how Java does it, but it works. I''m programming in Java daily at work, and I''m using this feature all the time. I think Java just creates the entire object, including vtables, before actually calling any constructors on the object. Perhaps it''s because Java supports RTTI (Run-time Type Identification) by default, which makes it possible to retrieve info on the classes themselves at runtime, whereas C++ compilers require you to enable it (possibly for performance reasons).

I really think this is so essential to OO programming, that I don''t understand why C++ doesn''t support it.

Dormeur
Wout "Dormeur" NeirynckThe Delta Quadrant Development Page
Since the only time I''ve ever seen anyone complain about it in this thread, I suppose it''s not as essential as you claim, is it?

This topic is closed to new replies.

Advertisement