PDA

View Full Version : Segment Fault error - libpng



kieranlavelle
01-10-2017, 04:34 PM
I seem to be getting a segment fault error from one of my methods that uses libpng. I have ran the gode in gdb and got the following trace:



Thread 1 "clockProject" received signal SIGSEGV, Segmentation fault.
__memcpy_sse2_unaligned () at ../sysdeps/x86_64/multiarch/memcpy-sse2-unaligned.S:38
38 ../sysdeps/x86_64/multiarch/memcpy-sse2-unaligned.S: No such file or directory.
(gdb) bt
#0 __memcpy_sse2_unaligned () at ../sysdeps/x86_64/multiarch/memcpy-sse2-unaligned.S:38
#1 0x00007ffff2e224de in ?? () from /usr/lib/x86_64-linux-gnu/dri/swrast_dri.so
#2 0x00007ffff2e228d2 in ?? () from /usr/lib/x86_64-linux-gnu/dri/swrast_dri.so
#3 0x00007ffff2e23342 in ?? () from /usr/lib/x86_64-linux-gnu/dri/swrast_dri.so
#4 0x00007ffff2e860ed in ?? () from /usr/lib/x86_64-linux-gnu/dri/swrast_dri.so
#5 0x00007ffff2e87d10 in ?? () from /usr/lib/x86_64-linux-gnu/dri/swrast_dri.so
#6 0x00007ffff2e12717 in ?? () from /usr/lib/x86_64-linux-gnu/dri/swrast_dri.so
#7 0x00007ffff2e141a0 in ?? () from /usr/lib/x86_64-linux-gnu/dri/swrast_dri.so
#8 0x0000000000402ceb in loadTexture(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int&, int&) ()
#9 0x0000000000404868 in init() ()
#10 0x0000000000404eed in keyboard(unsigned char, int, int) ()
#11 0x00007ffff7bafd1f in glutMainLoopEvent () from /usr/lib/x86_64-linux-gnu/libglut.so.3
#12 0x00007ffff7bb0145 in glutMainLoop () from /usr/lib/x86_64-linux-gnu/libglut.so.3
#13 0x0000000000404fa3 in main ()


The method in question is loadTexture:



GLuint loadTexture(std::string filename, int &width, int &height)
{
GLuint TEXTURE_LOAD_ERROR = 0;

//header for testing if it is a png
png_byte header[8];

//open file as binary
FILE *fp = fopen(filename.c_str(), "rb");
if (!fp) {
return TEXTURE_LOAD_ERROR;
}

//read the header
fread(header, 1, 8, fp);

//test if png
int is_png = !png_sig_cmp(header, 0, 8);
if (!is_png) {
fclose(fp);
return TEXTURE_LOAD_ERROR;
}

//create png struct
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
NULL, NULL);
if (!png_ptr) {
fclose(fp);
return (TEXTURE_LOAD_ERROR);
}

//create png info struct
png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) {
png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL);
fclose(fp);
return (TEXTURE_LOAD_ERROR);
}

//create png info struct
png_infop end_info = png_create_info_struct(png_ptr);
if (!end_info) {
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
fclose(fp);
return (TEXTURE_LOAD_ERROR);
}

//png error stuff, not sure libpng man suggests this.
if (setjmp(png_jmpbuf(png_ptr))) {
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
fclose(fp);
return (TEXTURE_LOAD_ERROR);
}

//init png reading
png_init_io(png_ptr, fp);

//let libpng know you already read the first 8 bytes
png_set_sig_bytes(png_ptr, 8);

// read all the info up to the image data
png_read_info(png_ptr, info_ptr);

//variables to pass to get info
int bit_depth, color_type;
png_uint_32 twidth, theight;

// get info about png
png_get_IHDR(png_ptr, info_ptr, &twidth, &theight, &bit_depth, &color_type,
NULL, NULL, NULL);

//update width and height based on png info
width = twidth;
height = theight;

// Update the png info struct.
png_read_update_info(png_ptr, info_ptr);

// Row size in bytes.
int rowbytes = png_get_rowbytes(png_ptr, info_ptr);

// Allocate the image_data as a big block, to be given to opengl
png_byte *image_data = new png_byte[rowbytes * height];
if (!image_data) {
//clean up memory and close stuff
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
fclose(fp);
return TEXTURE_LOAD_ERROR;
}

//row_pointers is for pointing to image_data for reading the png with libpng
png_bytep *row_pointers = new png_bytep[height];
if (!row_pointers) {
//clean up memory and close stuff
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
delete[] image_data;
fclose(fp);
return TEXTURE_LOAD_ERROR;
}
// set the individual row_pointers to point at the correct offsets of image_data
for (int i = 0; i < height; ++i)
row_pointers[height - 1 - i] = image_data + i * rowbytes;

//read the png into image_data through row_pointers
png_read_image(png_ptr, row_pointers);

//Now generate the OpenGL texture object
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D,0, GL_RGBA, width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*) image_data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

//clean up memory and close stuff
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
delete[] image_data;
delete[] row_pointers;
fclose(fp);

return texture;
}


This method is called from init() , which is re-called every time I press the 'i' key, I am using this as an odd way of changing my textures;

init():


void init()
{
int width, height;

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, 512, 0, 512);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);

if(texture_Increment > 3)
texture_Increment = 1;

switch (texture_Increment)
{
case 1: an_face_texture = loadTexture("images/planeClockFace.png", width, height);
hour_hand_texture = loadTexture("images/planeHand.png", width, height); x_hourScale = 100.0f; y_hourScale = 75.0f;
min_hand_texture = loadTexture("images/planeHand.png", width, height); x_minScale = 100.0f;
sec_hand_texture = loadTexture("images/planeHand.png", width, height); x_secScale = 75.0f;
r_value = 0;
g_value = 0;
b_value = 0;
break;
case 2: an_face_texture = loadTexture("images/NuklearClockFace.png", width, height);
hour_hand_texture = loadTexture("images/spaceHourHand.png", width, height); x_hourScale = 250.0f; y_hourScale = 75.0f;
min_hand_texture = loadTexture("images/spaceMinHand.png", width, height); x_minScale = 250.0f;
sec_hand_texture = loadTexture("images/planeHandSec.png", width, height); x_secScale = 75.0f;
r_value = 134;
g_value = 146;
b_value = 158;
break;
case 3: an_face_texture = loadTexture("images/SymbolClockFace.png", width, height);
hour_hand_texture = loadTexture("images/SymbolMinHand.png", width, height); x_hourScale = 200.0f; y_hourScale = 60.0f;
min_hand_texture = loadTexture("images/SymbolMinHand.png", width, height); x_minScale = 200.0f;
sec_hand_texture = loadTexture("images/planeHandSec.png", width, height); x_secScale = 75.0f;
r_value = 250;
g_value = 250;
b_value = 250;
break;
}

//The office background texture
background_texture = loadTexture("images/office-wall.png", width, height);

digital_face = make_digital_face();
background_wall = make_background_wall();
stopwatch_button = make_stopwatch_button();
an_clockface = make_an_clockface();
hour_hand = make_hour_hand();
min_hand = make_min_hand();
sec_hand = make_sec_hand();
digital_day = make_digitalDay_container();

glutPostRedisplay();
}


The segement fault happens when I press 'i' for the second time, I just can't figure out why it's happening.

Dark Photon
01-10-2017, 06:00 PM
Comment out the GL calls in loadTexture(). If it still crashes in loadTexture(), your problem doesn't appear to pertain to OpenGL. If it doesn't crash, then the GL calls may be related. If so, verify you have an active OpenGL context.

In any case, you can get more info on your problem if you compile -g and then run your app under valgrind ("valgrind YOURAPP").