0

我正在为 freeimage 编写一个小包装器,用于图像加载和像素抓取等。我有一个PImage处理所有加载和显示的类,其中包含一个PixelColorBuffer类。我使用PixelColorBufferfor 一种方便的方法unsigned char从 s 中获取 stexturebuffer并将它们转换为另一个名为的类color(我将其排除在外,因为它工作正常)。我还希望能够使用此类设置像素PixelColorBuffer,这就是它具有colortobufferbuffertocolor. 我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];

和类被编译成 aPImage并正确链接。我假设我在设置指针时做错了,这是我第一次处理指向指针的指针......但我一生都无法弄清楚我做错了什么。这是所有相关代码。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];
}
4

2 回答 2

5

这可能不是全部,而是两个明显的问题:

PImage::PImage() {
    this->pixels = new PixelColorBuffer((unsigned char *) texturebuffer);
}

此行无效,因为texturebuffer那里未初始化。(从未初始化的变量中读取会导致未定义的行为)。

PixelColorBuffer::PixelColorBuffer(unsigned char * b) {
    this->b = &b;
}

这条线指向this->bb它是 中的局部变量(参数)PixelColorBuffer::PixelColorBuffer。构造函数返回后,this->b是一个无效的指针。

于 2012-11-24T04:32:06.260 回答
2

this->b = &b;-- 您正在将 b 初始化为指向堆栈值的指针。

将参数更改为 aunsigned char*&以解决代码中的这个直接问题。要解决长期问题,请停止使用指针。(这会在其他地方导致错误,但它会修复此处未定义的行为!)

(unsigned char *)不要在 C++ 代码中使用 C 样式转换。使用 C++ 风格的演员表,它们既不那么危险,又能说出你打算做什么。

unsigned char ** b为什么你有一个指向无符号字符缓冲区指针的指针?为什么你在不知道它有多长的情况下拿着一个缓冲区闲逛?

texturebuffer = new GLubyte[4*w*h];在 C++ 中,使用某种所有权类来包装分配是一个好主意,这样您就知道哪个指针“拥有”数据,并负责清理它。

this->pixels = new PixelColorBuffer((unsigned char *) texturebuffer);你有什么理由PixelColorBuffer需要动态分配吗?为什么不在PixelColorBuffer你的类/结构中有一个实际的,而不是把它放在免费商店的开销和混乱?

首先,教一个PixelColorBuffer如何是空的。其次,不要动态分配它。第三,如果你编写一个分配内存的非平凡构造函数,你必须编写一个析构函数、一个复制构造函数和operator=. 您可以选择禁用复制构造函数,operator=而不是编写它们。(谷歌“三个 C++ 规则”)

然后每当你更新你的texturebuffer,告诉PixelColorBuffer指向一个新的像素源。这消除了对char**in的需要PixelColorBuffer

Ideally, store your texturebuffer in a managed buffer, like a std::vector instead of using new -- why manage memory when someone else can do it? This does away with a need to write a destructor (but you still need to disable = and copy construction).

于 2012-11-24T04:32:26.200 回答