复制构造函数中的SEG故障



我正在使用"图像"类操纵 *.ppm图像的作业。当调用复制构造函数时,它会编译,然后seg故障。在这里是:

Image::Image(const Image & imageToCopy) {
fileType = imageToCopy.fileType;
width = imageToCopy.width;
height = imageToCopy.height;
maxColor = imageToCopy.maxColor;
image = new int *[height];
for(int i=0; i < height; i++) {
    image[i] = new int [width];
    for(int j=0; j < width; j++) {
    image[i][j] = imageToCopy.image[i][j];
    }
}
}

这样称呼:

Image image2(image1);

我有些损失为什么会发生这种情况。我不知道怎么了,因为代码与我的构造函数几乎相同,后者正常。唯一的区别是我有

image[i][j] = imageToCopy.image[i][j];

而不是

imageInputStream >> image[i][j];

想法?谢谢

编辑:构造函数如下:

Image::Image(const char* filename) {
    ifstream imageInputStream;
    imageInputStream.open(filename);
    imageInputStream >> fileType;
    imageInputStream >> width;
    imageInputStream >> height;
    imageInputStream >> maxColor;
    image = new int *[height];
    for(int i=0; i < height; i++) {
        image[i] = new int [width];
        for(int j=0; j < width; j++) {
            imageInputStream >> image[i][j];
        }
    }
    imageInputStream.close();
}

而无需看到完整的代码,这只是一个猜测,但是如果您创建了一个复制构造函数和一个destuructor,却没有复制分配操作员,则可能会得到类似的segfault,如果您尝试使用分配。

,您可能不会认为自己在任何地方都在做分配,但是除非您知道C 的所有规则(即使是专家也没有,更少的新学生),很难确定。找出最简单的方法是声明私人分配运算符,不要定义它(或者,如果您使用的是C 11,请删除它),然后查看是否遇到了编译错误。

例如:

struct Image {
  int width_, height_;
  int **image_;
  Image(int width, int height) : width_(width), height_(height),
                                 image_(0) {
    image_ = new int *[height_];
    for (int i = 0; i != height_; ++i) {
      image_[i] = new int[width_];
      for (int j = 0; j != width_; ++j) {
        image_[i][j] = 1;
      }
    }
  }
  Image(const Image& rhs) : width_(rhs.width_), height_(rhs.height_),
                            image_(0) {
    image_ = new int*[height_];
    for (int i = 0; i != height_; ++i) {
      image_[i] = new int[width_];
      for (int j = 0; j != width_; ++j) {
        image_[i][j] = rhs.image_[i][j];
      }
    }
  }
  /* uncomment to uncrash
  Image& operator=(const Image& rhs) {
    if (this == &rhs) return *this;
    for (int i = 0; i != height_; ++i) {
      delete [] image_[i];
    }
    delete [] image_;
    image_ = new int*[height_];
    for (int i = 0; i != height_; ++i) {
      image_[i] = new int[width_];
      for (int j = 0; j != width_; ++j) {
        image_[i][j] = rhs.image_[i][j];
      }
    }
    return *this;
  }
  */
  ~Image() {
    for (int i = 0; i != height_; ++i) {
      delete [] image_[i];
    }
    delete [] image_;
  }
};
int main(int, char*[]) {
  Image img(200, 300);
  Image img2(img);
  Image img3(100, 200);
  img3 = img2;
  return 0;
}

正如评论所暗示的那样,如果您输入复制分配操作员,则整个事情都有效。

如果这是您的问题,请阅读三个规则(Wikipedia,Ward的Wiki)。

我将您粘贴在Pastebin粘贴的代码中,并在两个构造函数中添加了一些日志记录。

Image(const char *)中,在imageInputStream >> maxColor之后;:

    cout << "Image(" << filename << "): "
         << fileType << ", "
         << width << ", "
         << height << ", "
         << maxColor << endl;

Image(const Image&)中,maxColor = imageToCopy.maxColor;之后:

    cout << "Image(Image): "
         << fileType << ", "
         << width << ", "
         << height << ", "
         << maxColor << endl;

这是输出:

Testing standard constructor, opening tux.ppm
Image(tux.ppm): P3, 0, 0, 0
Calling flip method
Calling dither method
Saving the flipped and dithered image
Creating a 2nd image object, using tux.ppm again with the standard constructor
Image(tux.ppm): P3, 32767, 1656563112, 17

换句话说,您正在阅读垃圾。第一次,我碰巧读取0x0并返回一个空图像。然后,我阅读了32767x1656563112并创建一个巨大的垃圾图像,它花了很长时间,以至于我不想等待,但是我可以想象将其复制会segfault。

并确认是这种情况,请查看输出的内容,如tux_transformed.ppm:

P3
0 0
0

当然我没有您的tux.ppm文件,但是我从不同来源扔了一堆示例PPM,它们都有相同的问题。

疯狂地猜测,您的问题是您没有处理PPM评论,因此您正在尝试将其阅读为例如宽度。但这真的没关系。如果您的代码可以创建垃圾对象,它可能会崩溃尝试复制它们。

最新更新