1

So...

For the past couple days I have been writing an OpenGL program using GLFW and GLEW, and everything has been going mostly alright, until today. My program just crashes and tells me that there's an "access violation":

First-chance exception at 0x549E12F0 (atioglxx.dll) in OpenGLProject.exe: 0xC0000005: Access violation reading location 0x28F98511.

Unhandled exception at 0x549E12F0 (atioglxx.dll) in OpenGLProject.exe: 0xC0000005: Access violation reading location 0x28F98511.

The program '[7712] OpenGLProject.exe' has exited with code 0 (0x0).

I have Googled around a lot for an answer, or at least something similar, but to no avail. I don't think that the problem is my drivers, but it very well could be. But I believe that it is just my bad programming that is the problem here.

main.cpp:

#define UTIL_HEAD
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <math.h>

#define GL_HEAD
    #define GLEW_STATIC
    #include <glew.h>
    #include <glfw3.h>

#include "shaders.h"

const GLuint width = 800, height = 600;
GLuint renderer;

int kill() {
    std::cout << "Stopping!";

    //glDeleteVertexArrays();
    //glDeleteProgram();
    //glDeleteVertexArrays();

    glfwTerminate();
    return -1;
}

void windowInit() {
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);
}

void shaderInit() {
    renderer = compileShaders();
    GLuint vao;

    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);
}

void renderInit() {
    const GLfloat color[] = { (float)sin(glfwGetTime()) * 0.5f + 0.5f,
                              (float)cos(glfwGetTime()) * 0.5f + 0.5f,
                              0.0f, 1.0f };

    glClearBufferfv(GL_COLOR, 0, color);
}

int main() {

    windowInit();

    GLFWwindow * window = glfwCreateWindow(width, height, "Test", nullptr, nullptr);

    if (window == nullptr) {
        std::cout << "Failed to create GLFW window" << std::endl;
        kill();
    }
    glfwMakeContextCurrent(window);

    glewExperimental = GL_TRUE;
    if (glewInit() != GLEW_OK) {
        std::cout << "Failed to initialize GLEW" << std::endl;
        kill();
    }

    shaderInit();

    glViewport(0, 0, width, height);

    while (!glfwWindowShouldClose(window)) {
        glfwPollEvents();
        renderInit();
        glUseProgram(renderer);
        glDrawArrays(GL_POINTS, 0, 1);
        glfwSwapBuffers(window);
    }
    kill();
    return 0;
}
#ifndef UTIL_HEAD
    #define UTIL_HEAD
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <math.h>
#endif

Shader.hpp:

#ifndef UTIL_HEAD
    #define UTIL_HEAD
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <math.h>
#endif

#ifndef GL_HEAD
    #define GL_HEAD
    #define GLEW_STATIC
    #include <glew.h>
    #include <glfw3.h>
#endif

const char * fragment_shader_source;
const char * vertex_shader_source;

void loadVertexShader() {

    std::ifstream vertex("./shader_vtex.glsl");
    std::string vertex_shader_read;

    std::string vline;
    if (vertex.is_open()) {
        while (std::getline(vertex, vline)) {
            vertex_shader_read = vertex_shader_read + vline + '\n';
        }
        vertex.close();
    }
    else {
        std::cout << "error: (critical) unable to open vertex shader!" << '\n';
    }
    vertex_shader_source = vertex_shader_read.c_str();
}

void loadFragmentShader() {

    std::ifstream fragment("./shader_frag.glsl");
    std::string fragment_shader_read;

    std::string fline;
    if (fragment.is_open()) {
        while (std::getline(fragment, fline)) {
            fragment_shader_read = fragment_shader_read + fline + '\n';
        }
        fragment.close();
    }
    else {
        std::cout << "error: (critical) unable to open fragment shader!" << '\n';
    }
    fragment_shader_source = fragment_shader_read.c_str();
}

GLuint compileShaders() {

    GLuint vertex_shader;
    GLuint fragment_shader;
    GLuint program;

    loadVertexShader();
    loadFragmentShader();

    vertex_shader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertex_shader, 1, (const GLchar**)vertex_shader_source, NULL);
    glCompileShader(vertex_shader);

    fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(vertex_shader, 1, (const GLchar**)fragment_shader_source, NULL);
    glCompileShader(fragment_shader);

    program = glCreateProgram();
    glAttachShader(program, vertex_shader);
    glAttachShader(program, fragment_shader);
    glLinkProgram(program);

    glDeleteShader(vertex_shader);
    glDeleteShader(fragment_shader);

    return program;
}

You can find additional code (shaders, etc.) for this project at GitHub.

Thanks in advance for any help given!

  • `while (std::getline(vertex, vline))` Ugh. Why do people do this when loading files? Do they honestly think that this is a good way to load an entire file? Do a Google search about it; you'll find [plenty of alternatives](http://stackoverflow.com/a/2602258/734069), even on this very site. – Nicol Bolas Jan 17 '16 at 14:38
  • Sorry... I'm relatively new to C++ and this is the only way I thought of to read the file. I'll figure out a better solution! –  Jan 17 '16 at 14:40

1 Answers1

3

There is a problem with the shader loading: You only store the .cstr() pointer but not the string object. When then loadVertexShader method (or the loadFragmentShader method) goes out of scope and the vertex_shader_read object is deleted. When this happens the stored pointer points to an invalid memory address.

To fix the problem, you can, for example, store the string object itself instead of the pointer. But for a better design I would suggest to avoid global variables for such purpose anyhow.

BDL
  • 18,169
  • 14
  • 45
  • 47
  • 1
    Side-side-note:There is actually a VAO bound in this code (it's in `shaderInit()`). – derhass Jan 17 '16 at 13:45
  • Ok. I moved the content of the two functions into the body of compileShaders() since they were only called once, and it eliminates the use of global variables. But I still cant seem to figure out how to get the value of the variable which the pointer points to without the variable dying and taking the pointer with it. Any advice? –  Jan 19 '16 at 23:41