在析构函数中调用成员变量的虚函数会导致段错误
我遇到了一个非常奇怪的问题,我希望有人遇到过。
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());
}
当 Board 在析构函数中调用虚拟函数 letter->get() 的行超出范围时,程序会导致段错误。我正在使用 gcc 4.1.2。有什么想法吗?
更新
好吧,看起来实际代码中实际发生的情况与此等效:
class Board
{
public:
Board(){}
~Board()
{
std::cout << "Removing: " << letter->get() << std::endl;
}
void setLetter(Letter * l) { letter = l; }
private:
Letter* letter;
};
int main()
{
Board b;
A a;
b.setLetter(&a);
return 0;
}
在这种情况下,当调用虚函数时,A 已经超出了范围。
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;
};
int 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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我只能猜测您正在尝试将从 get() 返回的 std::string 转换为 char* 。否则我看不出崩溃的原因。
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.
gcc 4.5.2 没有问题
no problem in gcc 4.5.2
我没有意识到一个对象正在从堆栈传递给 setLetter(),因此 A 在 b 之前超出了范围。
I didn't realize an object was being passed to setLetter() from the stack, so A was going out of scope before b.
某些编译器不允许普通 C / C++ 构造函数或析构函数调用虚拟方法,似乎 (ANSI) C++ 规范也不允许。并且不推荐这样做。
有时这个要求是有用的。某些语言(例如 Object Pascal 显式)允许在构造函数和析构函数中调用虚拟方法。
您可以使用“假虚拟构造函数模式”来做一件事:
另一种解决方案是您安排代码,以便在析构函数之外显式调用您的虚拟方法。
干杯。
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":
Another solution its that you arrange your code so you explicit call your virtual method outside the destructor.
Cheers.