2012-11-24 94 views
0

我正在寫freeimage的一個小包裝器,用於圖像加載和像素抓取等等。我有一個PImage類,它負責處理所有的加載和顯示,並且裏面有一個PixelColorBuffer類。我使用PixelColorBuffer來方便地從texturebuffer中抓取unsigned char,並將它們轉換成另一個叫做color的類(因爲它工作正常,我排除了它)。我也希望能夠使用這個PixelColorBuffer類來設置像素,這就是爲什麼它具有colortobufferbuffertocolor。我使用指向unsigned char array的指針實例化PixelColorBuffer(注意:它包含圖片的rgba值)。然而,這似乎工作,但是當我打電話get(10, 10)被裝載在圖像上,並顯示我得到以下幾點:Segfault指向數組訪問的指針

(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]; 

PImagePixelColorBuffer類被編譯成.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]; 
} 
+1

我猜首先我會問,你的圖像大於10乘10? – Xymostech

+0

此代碼不完整也不正確,我敢打賭這不是最小的。 – Beta

+0

是的。幾百到幾百。如果是這樣的話,那將很有趣。 – jett

回答

2

this->b = &b; - 您正在初始化b是一個指向堆棧值的指針。

將參數更改爲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如何爲空。其次,不要動態分配它。第三,如果你編寫了一個分配內存的非平凡構造函數,你必須編寫一個析構函數,一個拷貝構造函數和operator=。您可以選擇禁用複製構造函數和operator=而不是編寫它們。 (谷歌「三C++規則」)

然後,無論何時你更新你的texturebuffer,告訴PixelColorBuffer指向一個新的像素來源。這擺脫了需要在PixelColorBuffer中有char**

理想情況下,將您的texturebuffer存儲在受管理的緩衝區中,如std::vector而不是使用new - 爲什麼在別人可以做到時管理內存?這消除了編寫析構函數的需求(但仍需要禁用=並複製構造)。

+0

謝謝你的建議。我從來不知道*&是一件事,所以我仍然有很多東西需要學習。我會研究C++貓,我假設你指的是我見過的動態/靜態排序?在你的問題:PixelColorBuffer不需要是動態的。 PixelColorBuffer上有析構函數和運算符 - 只是將它們排除在外。我認爲我是用雙指針來解決問題 - 因爲一個人也可以工作。我的印象是,在這種情況下使用矢量會比我想要的慢嗎?再次感謝你,我覺得我在這裏學到了很多東西。 – jett

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是一個無效的指針。

+1

悲劇繆斯? –

+0

我看到,我的印象是它會因爲紋理緩衝區被聲明而工作。我想我現在也明白函數的範圍(關於指針)。感謝您的幫助,瞭解了一些事情! – jett