我正在为freeimage编写一个小包装器,用于图像加载和像素抓取等。我有一个PImage
类来处理所有加载和显示,在其中它包含一个PixelColorBuffer
类。我使用PixelColorBuffer
以方便的方式从unsigned char
抓取texturebuffer
并将其转换为另一个名为color
的类(由于它工作正常,我将其排除在外)。我还希望能够使用此PixelColorBuffer
类设置像素,这就是colortobuffer
和buffertocolor
的原因。我使用指向PixelColorBuffer
的指针来实例化unsigned char array
(注意:它包含图片的rgba值)。但是,这似乎有效,但是当我在加载并显示的图像上调用get(10, 10)
时,我得到以下内容:
(GNU Debugger)
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7bc66d9 in cprocessing::PixelColorBuffer::buffertocolor (this=<optimized out>, n=<error reading variable: Unhandled dwarf expression opcode 0x0>) at pixelcolorbuffer.cpp:17
17 c.rgba[0]=(*b)[(n*4)+0];
PImage
和PixelColorBuffer
类被编译为.so
并正确链接。我假设我在设置指针时做错了,这是我第一次处理指针的指针......但我不能为我的生活弄清楚我做错了什么。这是所有相关的代码。
///MAIN_PROGRAM.CPP
PImage t;
t.loadImage("image.png"); //loads image (works)
image(t, mouseX, mouseY); //draws image (works)
color c = t.get(10, 10); //SEGFAULT
///PIMAGE.HPP
class PImage {
public:
GLubyte * texturebuffer; //holds rgba bytes here
PixelColorBuffer * pixels;
PImage();
color get(int x, int y);
};
///PIMAGE.CPP
PImage::PImage() {
this->pixels = new PixelColorBuffer((unsigned char *) texturebuffer);
}
void PImage::loadImage(const char * src) {
//...snip...freeimage loading / opengl code ...
char * tempbuffer = (char*)FreeImage_GetBits(imagen);
texturebuffer = new GLubyte[4*w*h];
//FreeImage loads in BGR format, so we swap some bytes
for(int j= 0; j<w*h; j++){
texturebuffer[j*4+0]= tempbuffer[j*4+2];
texturebuffer[j*4+1]= tempbuffer[j*4+1];
texturebuffer[j*4+2]= tempbuffer[j*4+0];
texturebuffer[j*4+3]= tempbuffer[j*4+3];
}
//...snip...freeimage loading / opengl code ...
}
color PImage::get(int x, int y) {
return pixels->buffertocolor((y*w)+x);
}
///PIXELCOLORBUFFER.HPP
class PixelColorBuffer {
public:
unsigned char ** b;
PixelColorBuffer(unsigned char * b);
/**Converts a pixel from the buffer into the color
* @param n pixel ((y*width)+x)
* @return color*/
color buffertocolor(int n);
/**Converts a pixel from the buffer into the color
* @param n pixel ((y*width)+x)
* @param c color to put into buffer*/
void colortobuffer(int n, const color& c);
};
///PIXELCOLORBUFFER.CPP
PixelColorBuffer::PixelColorBuffer(unsigned char * b) {
this->b = &b;
}
color PixelColorBuffer::buffertocolor(int n) {
color c(0, styles[styles.size()-1].maxA);
c.rgba[0]=(*b)[(n*4)+0];
c.rgba[1]=(*b)[(n*4)+1];
c.rgba[2]=(*b)[(n*4)+2];
c.rgba[3]=(*b)[(n*4)+3];
return c;
}
void PixelColorBuffer::colortobuffer(int n, const color& c) {
(*b)[(n*4)+0] = c.rgba[0];
(*b)[(n*4)+1] = c.rgba[1];
(*b)[(n*4)+2] = c.rgba[2];
(*b)[(n*4)+3] = c.rgba[3];
}
答案 0 :(得分:5)
这可能不是整个故事,而是两个明显的问题:
PImage::PImage() {
this->pixels = new PixelColorBuffer((unsigned char *) texturebuffer);
}
此行无效,因为texturebuffer
未初始化。 (从未初始化的变量读取会导致未定义的行为)。
PixelColorBuffer::PixelColorBuffer(unsigned char * b) {
this->b = &b;
}
此行在this->b
处指向b
,这是PixelColorBuffer::PixelColorBuffer
中的局部变量(参数)。构造函数返回后,this->b
是一个无效指针。
答案 1 :(得分:2)
this->b = &b;
- 您正在初始化b以成为指向堆栈值的指针。
将参数更改为unsigned char*&
以解决代码中的这个直接问题。要解决长期问题,请不要乱用指针。 (这会在其他地方引起错误,但它会修复未定义的行为!)
(unsigned char *)
不要在C ++代码中使用C样式转换。使用C ++样式转换,它们都不那么危险,并说出你打算做什么。
unsigned char ** b
为什么你有一个指向无符号字符缓冲区的指针?你为什么要闲着一个缓冲区而不知道它有多长?
texturebuffer = new GLubyte[4*w*h];
,最好使用某种所有权类来包装分配,这样你就知道什么指针“拥有”数据,并负责清理它。
this->pixels = new PixelColorBuffer((unsigned char *) texturebuffer);
您的PixelColorBuffer
需要动态分配是否有任何理由?为什么不在你的类/结构中有一个实际的PixelColorBuffer
,而不是把它放在免费商店上的开销和混乱?
首先,教导PixelColorBuffer
如何为空。其次,不要动态分配它。第三,如果编写一个分配内存的非平凡构造函数,则必须编写析构函数,复制构造函数和operator=
。您可以选择禁用复制构造函数和operator=
,而不是编写它们。 (谷歌“三个C ++规则”)
然后,每当您更新texturebuffer
时,请告诉PixelColorBuffer
指向新的像素来源。这样就无需在char**
中使用PixelColorBuffer
。
理想情况下,将texturebuffer
存储在托管缓冲区中,例如std::vector
而不是new
- 为什么在其他人可以管理内存时管理内存?这消除了编写析构函数的需要(但您仍需要禁用=
并复制构造)。