Ошибка на указатель на доступ к массиву

Я пишу небольшую оболочку вокруг freeimage для загрузки изображений и захвата пикселей среди прочего. у меня есть PImage класс, который имеет дело со всей загрузкой и отображением, и внутри него он содержит PixelColorBuffer учебный класс. Я использую PixelColorBuffer для удобного способа захватить unsigned charс из texturebuffer и преобразовать их в другой класс под названием color (который я исключил, так как он работает нормально). Я также хочу иметь возможность устанавливать пиксели с помощью этого PixelColorBuffer класс, поэтому он имеет colortobuffer а также buffertocolor, Я создаю экземпляр PixelColorBuffer с указателем на где unsigned char array is (примечание: содержит значения 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

Решение

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= вместо того, чтобы писать их. (Google «правило трех C ++»)

Тогда всякий раз, когда вы обновляете texturebuffer, скажи PixelColorBuffer указать на новый источник пикселей. Это избавляет от необходимости иметь char** в PixelColorBuffer,

В идеале, хранить ваши texturebuffer в управляемом буфере, как std::vector Вместо того, чтобы использовать new — зачем управлять памятью, когда это может делать кто-то другой? Это избавляет от необходимости писать деструктор (но вам все равно нужно отключить = и копирование конструкции).

2

Другие решения

Это, вероятно, не вся история, а две очевидные проблемы:

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 неверный указатель

5

По вопросам рекламы [email protected]