我正在使用"图像"类操纵 *.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评论,因此您正在尝试将其阅读为例如宽度。但这真的没关系。如果您的代码可以创建垃圾对象,它可能会崩溃尝试复制它们。