我有一个在我的驱动程序中调用时不执行的功能。我通过printf语句逐行调试它,但无论我将它们放在我的函数中,我都无法显示它们中的任何一个。该功能不会产生预期的结果 - 写入图像文件。
void WriteImage(char *filename, Image &img)
{
printf("writing\n");
FILE *f = fopen(filename, "wb");
if (f == NULL)
{
fprintf(stderr, "Can't open file %s to write.\n", filename);
return;
}
fprintf(f, "P6\n");
fprintf(f, "%d %d\n", img.GetX(), img.GetY());
fprintf(f, "%d\n", 255);
fwrite(img.GetData(), sizeof(PixelStruct), img.GetX() * img.GetY(), f);
fclose(f);
}
这是从我知道有效的C函数中获取的代码,因此我不知道发生了什么。有什么想法吗?
编辑:
对于它的价值,当它被自己调用并且只有它本身时它才会执行。当我事先调用前面的ReadImage时,WriteImage不会执行。这是ReadImage:
void ReadImage(char *filename, Image &output)
{
FILE *f = fopen(filename, "rb");
char magicNum[128];
int width, height, maxval;
if (f == 0)
{
fprintf(stderr, "Unable to open file %s\n", filename);
exit(0);
}
fscanf(f, "%s\n%d %d\n%d\n", magicNum, &width, &height, &maxval);
printf("Magic num = %s width = %d, height = %d, maxval = %d\n",
magicNum, width, height, maxval);
if (strcmp(magicNum, "P6") != 0)
{
fprintf(stderr, "Unable to read from file %s, because it is not a PNM file of type P6\n", filename);
exit(1);
}
output.ResetSize(width, height);
PixelStruct *data = output.GetData();
output = Image(width, height, data);
fread(output.GetData(), sizeof(PixelStruct), width*height, f);
fclose(f);
}
编辑2:主要功能。
int main(int argc, char *argv[])
{
Image img;
ReadImage(argv[1], img);
printf("ReadImage called.\n");
WriteImage(argv[2], img);
}
编辑3:参数化构造函数。
Image::Image(int width, int height, PixelStruct* data)
{
this->x = width;
this->y = height;
this->data = data;
}
编辑4:图像。
struct PixelStruct
{
unsigned char red;
unsigned char green;
unsigned char blue;
};
class Image
{
private:
int x;
int y;
PixelStruct *data;
public:
Image(void); /* Default constructor */
Image(int width, int height, PixelStruct* data); /* Parameterized constructor */
Image(Image &); /* Copy constructor */
void ResetSize(int width, int height);
int GetX();
int GetY();
PixelStruct* GetData();
void SetData(PixelStruct *data);
};
Image::Image(void)
{
x = 0;
y = 0;
data = 0;
}
Image::Image(int width, int height, PixelStruct* data)
{
this->x = width;
this->y = height;
this->data = data;
}
Image::Image(Image &img)
{
this->x = img.x;
this->y = img.y;
this->data = img.data;
}
void Image::ResetSize(int width, int height)
{
this->x = width;
this->y = height;
}
int Image::GetX()
{
return x;
}
int Image::GetY()
{
return y;
}
PixelStruct* Image::GetData()
{
return data;
}
答案 0 :(得分:1)
这只是一个部分答案,因为有更好的方法来设计你的类,(也取决于你是否可以使用c ++ 11结构)但我能想到的最短路径来修复你的程序如下:
1.在构造函数中分配内存并在析构函数中释放它:
Image::Image(int width, int height)
{
this->x = width;
this->y = height;
this->data = new PixelStruct[width*height];
}
Image::~Image()
{
delete[] data;
}
2.删除默认构造函数,复制构造函数和调整大小方法
3.修改您的读取图像功能
Image* ReadImage(char *filename)
{
.
.
.
//read image size
Image *output = new Image(width, height);
fread(output->GetData(), sizeof(PixelStruct), width*height, f);
fclose(f);
return output;
}
4.将您的主要修改为:
int main(int argc, char *argv[])
{
Image* img= ReadImage(argv[1]);
printf("ReadImage called.\n");
WriteImage(argv[2], *img);
}
同样,这不是推荐的方法,但它应该使您的代码无需太多修改和新概念的介绍即可运行。
答案 1 :(得分:1)
您的类在数据成员方面存在许多内存管理问题。让我从你的具体问题开始
Image img;
ReadImage(argv[1], img);
此时img的缓冲区为0。
output.ResetSize(width, height); // Buffer is still 0
PixelStruct *data = output.GetData(); // data is 0
output = Image(width, height, data); // data is still zero
这里有内存问题。您没有赋值运算符。在这种特殊情况下,它没有真正的效果,但从长远来看可能会杀了你。你可能应该有一个工作
ouput.ResetSize (width, height) ;
(如下所述),没有其他陈述。
fread(output.GetData(), sizeof(PixelStruct), width*height, f); // data is still 0
我很惊讶你没有对被释放的人进行打击。
修复:
这些函数应该为数据分配一个缓冲区。
Image(int width, int height, PixelStruct* data);
void ResetSize(int width, int height);
此功能
Image(Image &); /* Copy constructor */
应该复制数据(不只是指定指针)。您需要一个具有相同功能但仍应删除任何现有数据的赋值运算符。
你应该有一个释放数据的析构函数。