Segfault复制构造函数

时间:2010-02-09 05:19:25

标签: constructor copy segmentation-fault

我的代码如下:

void Scene::copy(Scene const & source)    
{
maxnum=source.maxnum;
imagelist = new Image*[maxnum];

for(int i=0; i<maxnum; i++)
{
   if(source.imagelist[i] != NULL)
   {
    imagelist[i] = new Image;
    imagelist[i]->xcoord = source.imagelist[i]->xcoord;
    imagelist[i]->ycoord = source.imagelist[i]->ycoord;
    (*imagelist[i])=(*source.imagelist[i]);
   }

   else
   {
   imagelist[i] = NULL;
   }
}
}

一点背景:Scene类在构造时有一个名为maxnum的私有int和一个动态分配的Image指针数组。这些指针指向图像。复制构造函数尝试对阵列中的所有图像进行深层复制。不知怎的,我得到了一个Segfault,但我看不出我将如何访问一个超出界限的数组。

有人看错了吗?

我是C ++的新手,所以它可能是显而易见的。

谢谢,

2 个答案:

答案 0 :(得分:0)

我建议maxnum(也许是imagelist)成为私有数据成员并实现const getMaxnum()setMaxnum()方法。但我怀疑这是你描述这种情况的任何段错误的原因。

我会尝试在引用之前删除该const并实现const公共方法来提取数据。它可能编译,因为它只是一个参考。此外,我会尝试切换到指针而不是通过引用传递。

或者,您可以创建单独的Scene类对象,并将Image类型数据作为数组指针传递。我认为你不能声明Image *imagelist[value];

void Scene::copy(Image *sourceimagelist, int sourcemaxnum) {  
maxnum=sourcemaxnum;
imagelist=new Image[maxnum];
//...
    imagelist[i].xcoord = sourceimagelist[i].xcoord;
    imagelist[i].ycoord = sourceimagelist[i].ycoord;
//...
}
//...
Scene a,b;  
//...
b.Copy(a.imagelist,a.maxnum);

答案 1 :(得分:0)

如果源Image的maxnum设置高于其imagelist中的实际项目数,则循环将超过source.imagelist数组的末尾。也许maxnum在数组开始为空时被初始化为值1(或者maxnum可能根本没有被初始化),或者如果你有一个Scene :: remove_image()函数,它可能已经删除了一个没有递减的图像列表条目MAXNUM。我建议使用std :: vector而不是原始数组。向量将跟踪它自己的大小,因此你的for循环将是:

for(int i=0; i<source.imagelist.size(); i++)

并且它只能访问与持有的源向量一样多的项目。崩溃的另一个可能的解释是source.imagelist中的一个指针属于已删除的Image,但指针从未设置为NULL,现在是一个悬空指针。

delete source.imagelist[4];
...
...  //  If source.imagelist[4] wasn't set to NULL or removed from the array,
...  //  then we'll have trouble later.
...
for(int i=0; i<maxnum; i++)
{
    if (source.imagelist[i] != NULL)  //  This evaluates to true even when i == 4
    {
        //  When i == 4, we're reading the xcoord member from an Image
        //  object that no longer exists.
        imagelist[i]->xcoord = source.imagelist[i]->xcoord;

最后一行将访问它不应该访问的内存。也许对象仍然存在于内存中,因为它还没有被覆盖,或者它可能已被覆盖并且您将检索无效的xcoord值。如果你很幸运,那么你的程序就会崩溃。如果您直接处理new和delete,请确保在删除指针后将其设置为NULL,这样您就没有悬空指针。但是,如果您在某处保留指针的副本,则不会阻止此问题,在这种情况下,当您删除第一个副本时,第二个副本不会设置为NULL。如果您以后尝试访问指针的第二个副本,您将无法知道它不再指向有效对象。

使用智能指针类更安全,让它为您处理内存管理。标准C ++库中有一个名为std :: auto_ptr的智能指针,但它具有奇怪的语义,不能在C ++容器中使用,例如std :: vector。如果您安装了Boost库,那么我建议用boost :: shared_ptr替换原始指针。