Reading file, corrupted data

拟墨画扇 提交于 2020-01-23 17:31:28

问题


It seems I can't have my GLSL shaders compiled. Once in a while (mainly after editing a file), I get following error while compiling:

----- SRC ----- (150 B)
#version 330 core

uniform mat4 mvpMatrix;

in vec4 vertexPosition_modelspace;

void main() {
    gl_Position = mvpMatrix * vertexPosition_modelspace;
}
gp!
----- END -----
SimpleTransform.vertexshader:Vertex shader failed to compile with the following errors:
ERROR: 0:10: error(#132) Syntax error: 'gp' parse error
ERROR: error(#273) 1 compilation errors.  No code generated

It's quite strange since I swear the file doesn't contain that awkward gp! part. Nevertheless I investigated it with cat

#version 330 core

uniform mat4 mvpMatrix;

in vec4 vertexPosition_modelspace;

void main() {
    gl_Position = mvpMatrix * vertexPosition_modelspace;
}

and less

#version 330 core

uniform mat4 mvpMatrix;

in vec4 vertexPosition_modelspace;

void main() {
    gl_Position = mvpMatrix * vertexPosition_modelspace;
}

and both of them proved me right.

I wonder what's causing this strange behaviour.

Here's link to my project. You should be able to easily compile it by entering src directory and typing make (Linux only). It requires GLFW, GLEW, GLM and GL3.

And the code itself:

Loading shader files

GLuint shader_load(GLenum type, const char filename[]) {
    if ((type != GL_VERTEX_SHADER && type != GL_FRAGMENT_SHADER) || !filename) return 0;

    /* wczytywanie pliku shadera */
    FILE *file = fopen(filename, "rb"); 

    //okreslenie rozmiaru pliku
    fseek(file, 0, SEEK_END);   
    uint32 iFileSize = ftell(file);
    fseek(file, 0, SEEK_SET);

    //wczytywanie
    char *tmp = new char[iFileSize];
    memset(tmp, 0, sizeof(tmp));
    uint32 iBytes = (uint32) fread(tmp, sizeof(char), iFileSize, file); 
    fclose(file);   
    if (iBytes != iFileSize) printf("Warning: reading error possible!\n");

    #ifdef _DEBUG_
    printf("----- SRC ----- (%d B)\n%s\n----- END -----\n", iBytes, tmp);
    #endif

    /* przygotowanie shadera */
    GLuint shader = glCreateShader(type);
    glShaderSource(shader, 1, const_cast<const GLchar**>(&tmp), NULL);
    delete[] tmp;
    glCompileShader(shader); //kompilacja shadera

    /* sprawdzenie statusu kompilacji */
    int status = GL_FALSE; 
    glGetShaderiv(shader, GL_COMPILE_STATUS, &status);  
    int logsize = 0;
    glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logsize);
    char *log = new char[logsize];
    glGetShaderInfoLog(shader, logsize, NULL, log);
    printf("%s:%s", filename, log);         
    delete[] log;
    if (status != GL_TRUE)  return 0;

    return shader;
}

回答1:


FIRST OFF Switch to C++ instead of C-with-a-cpp extension to avoid shipwrecks like this.

Analysis:


Running under valgrind shows

==15579== Invalid read of size 1
==15579==    at 0x5B95C65: vfprintf (vfprintf.c:1623)
==15579==    by 0x5B9E768: printf (printf.c:35)
==15579==    by 0x4019C1: shader_load(unsigned int, char const*) (shaders.cpp:88)
==15579==    by 0x401B30: program_create(char const*, char const*) (shaders.cpp:120)
==15579==    by 0x401D65: main (in /tmp/ogl-jg-3/test)
==15579==  Address 0xb3018a6 is 0 bytes after a block of size 150 alloc'd
==15579==    at 0x4C2864B: operator new[](unsigned long) (vg_replace_malloc.c:305)
==15579==    by 0x401961: shader_load(unsigned int, char const*) (shaders.cpp:81)
==15579==    by 0x401B30: program_create(char const*, char const*) (shaders.cpp:120)
==15579==    by 0x401D65: main (in /tmp/ogl-jg-3/test)

It tells you exactly that it tries to read beyond the end of the buffer tmp which is allocated in line 81. It seems you are somehow assuming it is null-terminated. Which it isn't. Add that:

//wczytywanie
char *tmp = new char[iFileSize+1];
memset(tmp, 0, (iFileSize+1)*sizeof(char));
uint32 iBytes = (uint32) fread(tmp, sizeof(char), iFileSize, file); 
fclose(file);   
if (iBytes != iFileSize) printf("Warning: reading error possible!\n");

#ifdef _DEBUG_
    printf("----- SRC ----- (%d B)\n%s\n----- END -----\n", iBytes, tmp);
#endif

And I get semi-decent output. The GL window stays blank, though

Update

To make it clearer what I meant by switch to C++ here's the idea:

GLuint shader_load(GLenum type, const char filename[]) {
    if ((type != GL_VERTEX_SHADER && type != GL_FRAGMENT_SHADER) || !filename) return 0;

    GLuint shader = glCreateShader(type);
    std::string src;
    {
        /* wczytywanie pliku shadera */
        std::ifstream ifs(filename, std::ios::binary);
        if (!std::getline(ifs, src, '\0'))
            std::cerr << "Warning: reading error possible!\n";
    }

#ifdef _DEBUG_
    std::cout << "----- SRC ----- " << src.size() << " B \n" << src << "\n----- END -----\n";
#endif

    /* przygotowanie shadera */
    const GLchar* sources[] = { src.c_str() };
    glShaderSource(shader, 1, sources, NULL);
    glCompileShader(shader); //kompilacja shadera


来源:https://stackoverflow.com/questions/12117720/reading-file-corrupted-data

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!