通过析构函数删除动态成员会导致程序挂起

时间:2013-05-26 01:41:30

标签: c++ vector copy

这是我的主要工作班,完成所有高级操作:

class Image
{
public:
    Image();
    Image(const Image& copy);
    ~Image();

    void loadimage(string filename);
    void saveimage(string filename);
    Image superimpose(const Image& ontop, Color mask);

    int getwidth();
    int getheight();
    Image operator=(const Image&);

protected:    
    vector< vector<Color> > pixels;
    int width;
    int height;
    ImageLoader* loader;
};

它有一个复制构造函数:

Image::Image(const Image& copy)
{
    width = copy.width;
    height = copy.height;
    loader = copy.loader;

    pixels = copy.pixels;
}

和一个重载的operator =方法:

Image Image::operator=(const Image& other)
{   
    width = other.width;
    height = other.height;
    loader = other.loader;

    pixels = other.pixels

    // Return this instance
    return *this;
}

析构函数是:

Image::~Image()
{
    delete loader;
}

loadimage()方法创建了一个新的动态分配加载器:

if(magic_number == "P3")
{
    loader = new P3Loader;
}
else if (magic_number == "P6")
{
    loader = new P6Loader;
}
else
{
    exit(1);  // If file is of an inappropriate format
}

当我运行该程序时,它会挂起。

编辑:该帖子已经过编辑以反映问题。请参阅Praetorian解决问题的解决方案。

1 个答案:

答案 0 :(得分:2)

您尚未发布Image::loader成员的初始化方式,但我假设它是这样的:

Image::Image()
: loader(nullptr)
{
  // do stuff
  // then initialize loader
  loader = new ImageLoader(...);
}

同样,~Image()的定义缺失,所以我做了另一个假设:

Image::~Image()
{
  delete loader;
}

在复制构造函数(和赋值运算符)中,您只需从另一个Image对象复制指针,这样两个loader成员现在都指向同一个ImageLoader对象。当第一个对象的析构函数运行它delete ImageLoader对象时,第二个对象的析构函数将再次尝试delete同一个对象。这种双重删除是未定义的行为,可能是您的程序崩溃的原因。

您需要在复制构造函数和赋值运算符中制作ImageLoader对象的深层副本。它可能看起来像这样:

loader = new ImageLoader(*other.loader); // invokes ImageLoader's copy ctor