读取文件,数据损坏

Posted

技术标签:

【中文标题】读取文件,数据损坏【英文标题】:Reading file, corrupted data 【发布时间】:2012-08-24 23:04:17 【问题描述】:

我的 GLSL 着色器 似乎无法编译。偶尔(主要是在编辑文件之后),编译时出现以下错误:

----- 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

这很奇怪,因为我发誓该文件不包含那个尴尬的gp! 部分。尽管如此,我还是用 cat

调查了它
#version 330 core

uniform mat4 mvpMatrix;

in vec4 vertexPosition_modelspace;

void main() 
    gl_Position = mvpMatrix * vertexPosition_modelspace;

#version 330 core

uniform mat4 mvpMatrix;

in vec4 vertexPosition_modelspace;

void main() 
    gl_Position = mvpMatrix * vertexPosition_modelspace;

他们都证明了我是对的。

我想知道是什么导致了这种奇怪的行为。

这里是my project 的链接。您应该可以通过进入 src 目录并输入 make(仅限 Linux)轻松编译它。它需要 GLFW、GLEW、GLM 和 GL3。

还有代码本身:

加载着色器文件

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;

【问题讨论】:

请在此处显示您的相关代码,您将获得比等待有人下载和挖掘您的项目更好的响应。我猜想不以 null 结尾的着色器字符串存在一些问题。 不要把你的项目发给我,让我使用一些复杂的依赖于平台的构建过程来构建它。只需发布相关代码(很可能是着色器加载代码)。即使您删除了项目并且链接在下周失效,这种情况也会持续。 @ChristianRau 添加了加载着色器源代码 此外,如果您使用 gDEBugger,您可以查看每个着色器实际发送到显卡的代码。 (并非所有显卡驱动在报错时都会显示着色器源代码) Added a sample snippet that shows how the fragment would have been written using std::string 而不是玩弄原始数组,memset,逐个和毛茸茸的演员表:) 【参考方案1】:

FIRST OFF切换到 C++ 而不是 C-with-a-cpp 扩展,以避免像这样的沉船。

分析:


在 valgrind 下运行显示

==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)

它准确地告诉您它试图读取缓冲区tmp 的末尾,该缓冲区在第 81 行分配。您似乎以某种方式假设它是空终止的。它不是。补充一点:

//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

我得到了半体面的输出。但是 GL 窗口保持空白

更新

为了让我的意思更清楚,切换到 C++ 的想法如下:

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

【讨论】:

@datenwolf 我永远不会知道,因为我不做图形编程,也不知道 API :) 感谢您的有用说明 当你切换到 C++ 时,为什么还要使用 C 文件之类的而不是仅仅做一个简单的 std::istream file(filename); std::string tmp(std::istreambuf_iterator&lt;char&gt;(file), (std::istreambuf_iterator())); 而不是整个 freadresize 混乱(不是说明确的 @ 987654328@)?你的代码实际上并不比他的 C/C++ 少。 @ChristianRau 主要是因为 (a) 它与问题无关 (b) 它与答案无关 (c) 这不是我的问题。但既然你有一个公平的观点,我更新了答案 :) @sehe 我同意这不是您的问题,也与问题无关,但是由于您明确建议他从 C/C++ 切换到正确的 C++,因此这与答案非常相关。

以上是关于读取文件,数据损坏的主要内容,如果未能解决你的问题,请参考以下文章

Logstash无法读取文件的更新内容

移动磁盘文件或目录损坏且无法读取文件怎样恢复

文件或目录损坏无法读取

文件或目录已损坏且无法读取

文件或目录已损坏且无法读取。请运行chkdsk工具

无法访问机械硬盘提示文件或目录损坏且无法读取的文件找回方案