读取文件,数据损坏
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 usingstd::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<char>(file), (std::istreambuf_iterator()));
而不是整个 fread
和 resize
混乱(不是说明确的 @ 987654328@)?你的代码实际上并不比他的 C/C++ 少。
@ChristianRau 主要是因为 (a) 它与问题无关 (b) 它与答案无关 (c) 这不是我的问题。但既然你有一个公平的观点,我更新了答案 :)
@sehe 我同意这不是您的问题,也与问题无关,但是由于您明确建议他从 C/C++ 切换到正确的 C++,因此这与答案非常相关。 以上是关于读取文件,数据损坏的主要内容,如果未能解决你的问题,请参考以下文章