【问题标题】:Virtual Classes Segmentation Faults虚拟类分段错误
【发布时间】:2010-03-07 03:08:20
【问题描述】:

我正在开发一个图形应用程序。它大量使用了虚拟类。我遇到了一些无法调试的分段错误。

此应用程序中的主要类是:

  • 形状(虚拟类)
    • 矩形
    • 多边形
    • 圈子
  • 图片(本质上是形状的集合)

这是我的代码适用部分的简短副本:

class Picture
{
  ...
  Picture(Graphics& gd)
  {
    gfx = &gd;
  }

  void Picture::draw() const
  {
    for(int i=0; i<shapes.size();i++)
    {
      shapes[i]->draw(*gfx);  // This line causes a segmentation fault
    }
  }
...
private:
  std::vector<Shape*> shapes;
  Graphics* gfx;
}

class Shape
{
...
virtual void draw(Graphics& g) const = 0;
...
}

这是一个显示一些信息的 gdb 会话:

程序以信号 11 终止,分段错误。 【新工艺89330】 #0 0x00020d38 in Rectangle::draw (this=0x41e10, g=@0xffbff904) 在矩形.cpp:42 42 g.setColor(getFillColor()); (gdb) 打印 &g $1 = (类图形 *) 0xffbff904 (gdb) BT #0 0x00020d38 in Rectangle::draw (this=0x41e10, g=@0xffbff904) 在矩形.cpp:42 #1 0x0001bae8 in Picture::draw (this=0xffbff950) at picture.cpp:45 #2 0x0002394c 在 writePicture (p= { = {_vptr.Figure = 0x2be38},形状 = { >> = {_M_impl = {> = {> = {},},_M_start = 0x3f648,_M_finish = 0x3f664,_M_end_of_storage = 0x3f664}},},gfx = 0xffbff904} , 文件名= {静态 npos = 4294967295, _M_dataplus = {> = {> = {}, }, _M_p = 0x3f49c "t1.dat.eps"}}) 在 testpicture.cpp:51 #3 0x00023b3c 在 simpleTest (inFileName= {静态 npos = 4294967295, _M_dataplus = {> = {> = {}, }, _M_p = 0x3fe24 "t1.dat"}}, outFileName= {静态 npos = 4294967295, _M_dataplus = {> = {> = {}, }, _M_p = 0x3f49c "t1.dat.eps"}}, bb=@0xffbff9c8) 在 testpicture.cpp:70 #4 0x00024c3c in main (argc=2, argv=0xffbffa74) at testpicture.cpp:165

我已经用头撞墙了几个小时,试图弄清楚这件事。它与 Picture 类的 Graphic 成员有关。但是,我看不到它是如何拼凑起来造成分段错误的。

编辑:

这是 testpicture.cpp 中创建 Graphics 对象的部分:

RectangularArea getPictureBounds (string fileName)
{
  ifstream in (fileName.c_str());

  PSGraphics gr(fileName + ".bb");
  Picture p0(gr);

  Shape* shape;
  while (in >> shape)
  {
    if (shape != NULL)
      p0.add(*shape);
  }
  return p0.boundingBox();
}

Graphic 也是一个虚拟类。在这种情况下,PSGraphic 继承自它。

【问题讨论】:

  • 你能发布testpicture.cpp - 看起来问题就在那里。 Graphics 实例是如何分配的?
  • 通过地址可以看出它是从栈中分配的(自动存储)。
  • 是的,这很明显。希望问题让 OP 怀疑地查看代码的其他部分。
  • 我在创建图形对象的地方添加了 testpicture.cpp 代码。如果这个对象在堆栈上,我怎样才能把它的副本放在堆上?没有克隆功能(我无法添加克隆功能)。如果使用标准副本,则相关数据将被剥离,因为 Graphic 是虚拟的。
  • in &gt;&gt; shape 在这里看起来很可疑 - 很可能它只是将一些整数读入指针,而不是像您期望的那样分配 Shape 子类。

标签: c++ gdb segmentation-fault virtual-functions


【解决方案1】:

gfx 指向堆栈中的一个对象。当您尝试绘制时,您确定对象仍然存在(在原来的位置)吗?

【讨论】:

  • 这是一个很好的观点。由于没有可用的 clone() 函数,我如何将这个对象放在堆上?
  • 通过operator new来分配,或者放到某个从堆中分配的对象中。
【解决方案2】:

将指向参数的指针存储为参考是不好的做法 - 这会造成内存所有权混淆。复制引用的对象(如果它是 value 类),或者更改方法以将 智能指针(如 boost::shared_ptr)带到共享资源。这样资源所有权管理就很明确了。

对于您的直接问题 - Graphics 实例可能已在堆栈上分配并超出范围,因此被破坏。然后你的Picture 代码引用了死对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-07-04
    • 2011-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-01
    相关资源
    最近更新 更多