OpenGL program works only in Debug mode in Visual Studio 2013

992 views Asked by At

my small OpenGL application works fine in Debug mode, but if I build it in Release mode I often get this error:

Shader Creation Error:
- Vertex shader failed to compile with the following errors:
ERROR: 0:22: error(#132) Syntax error: "]" parse error
ERROR: error(#273) 1 compilation errors.  No code generateder code here

The strange thing is, that the error occurs most of the time, but sometimes the program works fine. I think it has something to do with the filestream, but I cannot figure out what it is.

This is the corresponding part of my code:

    std::ifstream file(fp);
    if(!file) crit_error("Shader Loading", ("file "+fp+" doesn't exist").c_str());

    file.seekg(0, file.end);
    GLint len = GLint(file.tellg());
    file.seekg(0, file.beg);

    GLchar* buf = new GLchar[len];
    file.read(buf, len);
    file.close();

    std::string type = fp.substr(fp.size()-4, 4);
    if(type == ".vsh")
        id = glCreateShader(GL_VERTEX_SHADER);
    else if(type == ".fsh")
        id = glCreateShader(GL_FRAGMENT_SHADER);
    else if(type == ".csh")
        id = glCreateShader(GL_COMPUTE_SHADER);

    glShaderSource(id, 1, (const GLchar**)&buf, &len);
    glCompileShader(id);

    delete[] buf;
2

There are 2 answers

2
datenwolf On BEST ANSWER

Your problem lies here:

file.seekg(0, file.end);
GLint len = GLint(file.tellg());
file.seekg(0, file.beg);

GLchar* buf = new GLchar[len];
file.read(buf, len);
file.close();

This code reads exactly the length of the file and nothing more. And unfortunately file sizes don't actually tell you about how much there's actually to read; if the file read exits short it will leave in any garbage that was in the memory buf points to before it was allocated to your program. This explains why it works in debug mode: In debug mode buffers are usually allocated a little bit larger to allow for out-of-bounds access detection and variables and buffers left uninitialized by the programmer are set to zero. While useful for some debugging this may turn regular bugs into Heisenbugs.

Furthermore ifstream::read may return less than the requested amount of bytes, for example if you run into an end of file situation and leave the rest of the buffer untouched. As it happens ifstream::get will return NUL if you're hitting the end of file, so it will fill up your buffer with terminating NUL bytes.

The proper way to read a file being passed into C string processing functions is this:

file.seekg(0, file.end);
GLint len = GLint(file.tellg());
file.seekg(0, file.beg);

GLchar* buf = new GLchar[len + 1];
buf[len] = 0;
file.read(buf, len);
streamsize rb = file.gcount();
if( rb < len ) {
    /* file read short */
    /* either way zero out the remainder of
     * the buffer untouched by the read. */
    memset(buf + rb, 0, len - rb);

    /* should also log some warning message here. */
}
file.close();
7
bakkaa On

OK. I simply tried a different reading method and it worked.

    GLchar* buf = new GLchar[len];

    for(int i = 0; i < len; ++i)
        buf[i] = file.get();    

    file.close();

I think this is a bug of the Visual C++ compiler.