C++ 复制构造函数中的Seg错误
我正在做一个作业,在作业中我们使用“Image”类处理*.ppm图像。当调用复制构造函数时,它编译并seg错误。这是:C++ 复制构造函数中的Seg错误,c++,class,copy-constructor,C++,Class,Copy Constructor,我正在做一个作业,在作业中我们使用“Image”类处理*.ppm图像。当调用复制构造函数时,它编译并seg错误。这是: Image::Image(const Image & imageToCopy) { fileType = imageToCopy.fileType; width = imageToCopy.width; height = imageToCopy.height; maxColor = imageToCopy.maxColor; image = new int *[hei
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[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();
}
Image::Image(常量字符*文件名){
ifstream imageInputStream;
imageInputStream.open(文件名);
imageInputStream>>文件类型;
imageInputStream>>宽度;
imageInputStream>>高度;
imageInputStream>>maxColor;
图像=新整数*[高度];
对于(int i=0;i>图像[i][j];
}
}
imageInputStream.close();
}
在没有看到完整代码的情况下,这只是一个猜测,但是如果您创建了复制构造函数和析构函数,但没有复制赋值运算符,那么如果您尝试使用赋值,可能会得到与此完全相同的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;
}
正如注释所暗示的,如果取消对复制赋值操作符的注释,整个过程都会正常工作
如果这是您的问题,请仔细阅读三(,)规则。我获取了您粘贴在pastebin上的代码,并向两个构造函数添加了一些日志记录 在
Image(const char*)
中,在imageInputStream>>maxColor
的后面:
cout << "Image(" << filename << "): "
<< 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并创建了一个巨大的垃圾映像,这需要很长时间,我不想再等待了,但我可以想象复制它会出错
为了验证这一点,请查看输出为tux_transformed.ppm的内容:
P3
0 0
0
当然我没有你的tux.ppm文件,但是我从不同的来源向它扔了一堆ppm样本,它们都有相同的问题
作为一个粗略的猜测,您的问题是您没有处理PPM注释,所以您试图将其作为一个宽度来阅读。但这真的没关系。如果您的代码可以创建垃圾对象,那么在尝试复制它们时可能会崩溃。要复制的图像的宽度和高度是多少?如果大小正常,并且您没有得到一个
std::bad\u alloc
,乍一看就可以了。我建议您使用std::vector,而不是C样式的数组。。。我强烈建议这样做。事实上,如果您将内容存储为std::vector
,您可能甚至不需要复制构造函数……您能给我们一个最简单的完整示例吗?很可能你的image1
格式不好。驯鹿间接地提出了一个好的观点:为什么宽度需要锯齿状(每行不同),假设图像的每一行的像素数可能与其他每一行的像素数相同……您能否在问题中添加image
的声明……还有一个简单的问题:您是否有析构函数和赋值运算符?如果答案是“是”和“否”,您是否在做类似于Image img2的事情;img2=img1代码>任何地方?如果不使用赋值运算符,是否需要定义它。我知道,如果我像你在main中那样使用它,我需要它,但我不会对任何对象使用赋值。无论何时声明析构函数,都应该声明赋值运算符。否则,编译器将为您生成一个,这将是错误的。如果你确定你永远不会需要它,那么就声明它已被删除(C++11)或者声明它为私有,并且不定义它(C++03),但仍然声明它。(这样,如果你错了,你会得到一个编译器错误,而不是一个神秘的运行时崩溃。)好吧,瞧,让赋值操作符方法修复了它。我想这也会使很多复制构造函数代码过时,因为我可以创建一个新对象,并说image2=image1。谢谢,你可能想用另一个来定义一个。但最好的方法是另一种方法:定义swap
方法,然后根据复制和交换定义赋值运算符。然后,您不需要编写任何代码来检查自赋值、删除旧值等。有关详细信息,请参阅。
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
P3
0 0
0