Search code examples
c++openglglut

OpenGL crash just by removing std::cout<<"hi"<<std::endl from the program


I have found very mysterious problem where I commented out the debug line I have in program and the program "segmentaion fault (core dumped)".

I narrowed down the program and come to this. This is the whole code that reproduce the problem :

#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#include <highgui.h>
#include <GL/glut.h>
#include <iostream>

int main(int argc, char **argv)
{
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGBA | GLUT_ALPHA | GLUT_DEPTH | GLUT_DOUBLE);
  glutInitWindowSize(500, 281);
  (void) glutCreateWindow("Alpha Test");

  cv::Mat image = cv::imread("alphatest.png");
  int texWidth = image.cols;
  int texHeight = image.rows;
  GLuint texId;
  glGenTextures(1, &texId);
  glBindTexture(GL_TEXTURE_2D, texId);

  //std::cout << "hi" << std::endl;

  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, image.ptr());
}

This program crash at glTexImage2D with error message:

zsh: segmentation fault (core dumped)  ./mystery

(The program has been named mystery)

By uncommenting the cout line, the program runs fine without error along with message "hi". I wonder why I have to keep the debug line?

And this is alphatest.png enter image description here


Solution

  • Most likely your image row alignment does not meet default settings at which OpenGL does read images (4 byte row alignment). This may cause OpenGL to read from an unmapped page, causing a segfault. When doing that iostream output that may create a page allocation, adjacent to the image buffer so that this problem remains "hidden".

    Test this:

    glGenTextures(1, &texId);
    glBindTexture(GL_TEXTURE_2D, texId);
    glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);  /* tightly packed*/
    glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); /* tightly packed*/
    glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);   /* tightly packed*/
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);   /* tightly aligned*/
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, image.ptr());
    

    Furthermore if your image is grayscale, then reading a GL_BGRA format will expect more data than imread delivered. You should not hardcode these parameters, but determine them from the image file as imread returns.