0

画像の読み込みとピクセルのグラブなどのために、freeimage の周りに小さなラッパーを書いています。PImageすべての読み込みと表示を処理するクラスがあり、その中にPixelColorBufferクラスがあります。からを取得し、それらを と呼ばれる別のクラスに変換するPixelColorBuffer便利な方法としてを使用します(正常に動作するため除外しました)。また、このクラスを使用してピクセルを設定できるようにしたいので、 と があります。がどこにあるかへのポインターを使用してインスタンス化します(注: 画像の rgba 値を保持します)。ただし、これは機能しているようですが、ロードされて表示されている画像を呼び出すと、次のようになります。unsigned chartexturebuffercolorPixelColorBuffercolortobufferbuffertocolorPixelColorBufferunsigned char arrayget(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];
}
4

2 に答える 2

5

これがすべてではありませんが、2 つの明らかな問題があります。

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

が初期化されていないため、この行は無効ですtexturebuffer。(初期化されていない変数から読み取ると、未定義の動作が発生します)。

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

この行は、 のローカル変数 (パラメータ) である をthis->b指しています。コンストラクターが戻った後は、無効なポインターです。bPixelColorBuffer::PixelColorBufferthis->b

于 2012-11-24T04:32:06.260 に答える
2

this->b = &b;-- スタック値へのポインタになるように b を初期化しています。

引数を a に変更しunsigned 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空っぽになる方法を教えます。次に、動的に割り当てないでください。第 3 に、メモリを割り当てる自明でないコンストラクタを作成する場合は、デストラクタ、コピー コンストラクタ、およびoperator=. operator=それらを書き込む代わりに、コピー コンストラクターと を無効にすることを選択できます。(Google の「C++ の 3 つのルール」)

次に、 を更新するたびに、 に新しいピクセル ソースを指すtexturebufferように指示します。これにより、 inPixelColorBufferを持つ必要がなくなります。char**PixelColorBuffer

理想的には、メモリを使用する代わりにtexturebuffer、管理されたバッファに格納します。他の誰かがメモリを管理できるのに、なぜメモリを管理するのでしょうか。これにより、デストラクタを記述する必要がなくなります (ただし、構築を無効にしてコピーする必要はあります)。std::vectornew=

于 2012-11-24T04:32:26.200 に答える