开发者

Calling member variable's virtual function within destructor causes seg fault

开发者 https://www.devze.com 2023-03-25 11:07 出处:网络
I\'m having a very odd problem that I\'m hoping someone has come across. class Letter { public: Letter() virtual ~Letter()

I'm having a very odd problem that I'm hoping someone has come across.

class Letter
{
public:
    Letter()
    virtual ~Letter()
    virtual std::string get() const = 0;
};

class A : public Letter
{
public:
    A()
    ~A()
    virtual std::string get() const { return "A"; }
};

class Board
{
public:
   Board(){}
   ~Board()
   {
        std::cout << "Removing: " << letter->get() << std::endl;
        delete letter;
   }
   void setLetter(Letter * l) { letter = l }
private:
   Letter * letter;
}

int main()
{
    Board b;
    b.setLetter(new A());
}

The program causes a seg fault when Board goes out of scope at the line where the virtual function letter->get() is called in the destructor. I'm using gcc 4.1.2. Any ideas?

UPDATE

Okay, it seems what's actually happening in the real code is the equivalent of this:

class Board
{
public:
   Board(){}
   ~Board()
   {
       std::cout << "Removing: " << letter->get() << std::endl;
   }
   void setLetter(Letter * l) { letter = l; }
private:
   Letter* letter;
};

in开发者_如何学Got main()
{
    Board b;
    A a;
    b.setLetter(&a);

    return 0;
}

In which case A is already out of scope when the virtual function is called.


I can only guess you're attempting to cast the std::string returned from get() to a char*. Otherwise i see no reason for the crash.


#include <iostream>
#include <string>
using namespace std;

class Letter
{
public:
    Letter() {}
    virtual ~Letter() {}
    virtual std::string get() const = 0;
};

class A : public Letter
{
public:
    A() {}
    ~A() {}
    virtual std::string get() const { return "A"; }
};

class Board
{
public:
   Board(){}
   ~Board()
   {
        std::cout << "Removing: " << letter->get() << std::endl;
        delete letter;
   }
   void setLetter(Letter * l) { letter = l; }
private:
   Letter * letter;
};

int main()
{
    Board b;
    b.setLetter(new A());
    return 0;
}

no problem in gcc 4.5.2


I didn't realize an object was being passed to setLetter() from the stack, so A was going out of scope before b.

Board b;
A a;
b.setLetter(&a);


Some compilers doesn't allow Plain C / C++ constructors or destructors call virtual methods, seems like the (ANSI) C++ specification neither. And its not recommended.

Sometimes that requirement is useful. Some languages like Object Pascal explicit allow virtual methods calls within constructors and destructors.

One thing you can do its use the "Fake Virtual Constructor Pattern":

class MyClass
{
  public:
    // constructor
    MyClass
    {
      // anything but virtual methods
    }

    // destructor
    ~MyClass
    {
      // anything but virtual methods
    }

    virtual void MyFakeConstructor()
    {
      MyVirtualMethod();
    }

    virtual void MyFakeDestructor()
    {
      MyVirtualMethod();
    }

    virtual void MyVirtualMethod()
    {
      // more stuff
    }

    // more members
}

int main(char[][] Args)
{
  MyClass MyObject = new MyClass();
  MyObject->MyFakeConstructor(); // <-- calls "MyVirtualMethod()"

  MyObject->DoSomething1();
  MyObject->DoSomething2();
  MyObject->DoSomething3();

  MyObject->MyFakeDestructor(); // <-- calls "MyVirtualMethod()"
  delete MyObject;

  return 0;
} // int main()

Another solution its that you arrange your code so you explicit call your virtual method outside the destructor.

Cheers.

0

精彩评论

暂无评论...
验证码 换一张
取 消