OpenGL 和 SDL '#version required and missing' 但在调试中工作

Posted

技术标签:

【中文标题】OpenGL 和 SDL \'#version required and missing\' 但在调试中工作【英文标题】:OpenGL and SDL '#version required and missing' but working in debugOpenGL 和 SDL '#version required and missing' 但在调试中工作 【发布时间】:2014-12-17 15:21:21 【问题描述】:

我对 C++ 相当陌生,所以现在进入这种类型的东西可能有点为时过早,但无论如何。我一直在努力在 OpenGL 和 SDL 中设置一个简单的三角形,但我已经发生了一些奇怪的事情。第一件事是,当我编译它时,我得到三个错误之一:

Line 194: ERROR: Compiled vertex shader was corrupt.

Line 156: ERROR: 0:1: '' :  #version required and missing. ERROR: 0:1: '<' : syntax error syntax error

Line 126: ERROR: 0:1: '' :  #version required and missing.
ERROR: 0:1: 'lour' : syntax error syntax error

就像字面意思一样,我只是反复点击构建按钮,无论它显示一个消息还是另一个消息,它似乎都是完全随机的。好的,这很奇怪,但更奇怪的是,当我在调试模式下运行它(即我设置断点并逐步执行所有操作)时,它运行良好,没有明显的原因。

所以,我得出的结论是我在内存方面做了一些愚蠢的事情,但无论如何这里是相关代码(询问您是否想看更多):

读取文件功能

std::string readFile(std::string name) 

    std::ifstream t1(name.c_str());

    if (t1.fail()) 
        std::cout << "Error loading stream" << "\n";
    

    std::stringstream buffer;
    buffer << t1.rdbuf();
    std::string src = buffer.str();

    std::cout << src << std::endl;

    return src;


编译着色器

const char *vSource = readFile("vertexShader.gl").c_str();
// Read fragment shader
const char *fSource = readFile("fragmentShader.gl").c_str();

GLuint vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, &vSource, NULL);
glCompileShader(vs);

GLint isCompiled = 0;
glGetShaderiv(vs, GL_COMPILE_STATUS, &isCompiled);
if(isCompiled == GL_FALSE)  // ... Error stuff here...

N.B 有一个片段着色器编译位,看起来完全一样。第 126 行和第 156 行分别位于顶点着色器和片段着色器的错误部分。

链接着色器

shader_programme = glCreateProgram();
glAttachShader(shader_programme, vs);
glAttachShader(shader_programme, fs);
glLinkProgram(shader_programme);


GLint isLinked = 0;
glGetProgramiv(shader_programme, GL_LINK_STATUS, (int *)&isLinked);
if(isLinked == GL_FALSE)  // ... Error stuff ... 
glDetachShader(shader_programme, vs);
glDetachShader(shader_programme, fs);

您可以根据需要查看着色器,但它们可以工作(因为片段着色器在调试模式下显示正确的颜色)所以我不'认为它们是问题所在。

我在 OSX 上使用 SDL2、OpenGL v3.2、GLSL v1.50 和 Xcode 4(是的,如果你知道我的意思,我做了文本文件)。

很抱歉发布了很多代码 - 如果有人有任何关于如何在 Xcode 中调试内存泄漏的提示可能会有所帮助,但无论如何谢谢:)

【问题讨论】:

【参考方案1】:

您在读取导致 vSource 引用已删除内存(和未定义行为)的字符串后立即丢弃它们,而是将源保留为 std::string,而您需要 char* 保持有效:

std::string vSource = readFile("vertexShader.gl");
char* vSourcecharp = vSource.c_str();
// Read fragment shader
std::string fSource = readFile("fragmentShader.gl");
char* fSourcecharp = fSource.c_str();


GLuint vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, &vSourcecharp, NULL);
glCompileShader(vs);

【讨论】:

成功了!不过,我不完全确定如何。你说'我把琴弦扔掉'......通过哪条线?我想我对 c++ 的了解并不多…… :( 还是谢谢 @user3183526 readFile 返回一个临时的std::string 你立即在它上面调用c_str() 但是在行完成执行后临时被清理(并且返回的指针变得无效)。 我想我明白了...所以如果 vSource 对象不是指针,那么它会起作用吗? (不包括 gl 部分) @user3183526: readFile (...) 在您的代码中创建一个临时 C++ 字符串;在其上调用 c_str (...) 会创建一个 C 字符串(末尾带有 '\0' 的字符数组)并返回一个指向该数组的指针。真正的问题是它返回的数组没有分配在长期内存中(例如使用new)。一旦创建它的对象被销毁,指向的内存就可以被覆盖。您必须在它所属的 C++ 字符串存在时使用它,或者使用 strdup (...) 之类的东西制作长期副本。如果你使用strdup (...),你必须记住最终释放内存。 @AndonM.Coleman 虽然更容易想到:“如果临时结果需要比语句存活更长的时间,则将其放入局部变量中。”然后记住c_str 结果的有效性与string 的生命周期相关。

以上是关于OpenGL 和 SDL '#version required and missing' 但在调试中工作的主要内容,如果未能解决你的问题,请参考以下文章

同时从 SDL 和 OpenGL 渲染

用于包装 SDL 和 OpenGL 绘图方法的虚拟函数的替代方案

SDL2:如何同时拥有 SDL2 菜单和 OpenGL 上下文?

SDL_Renderer opengl 冲突

使用 SDL 和 OpenGL 调整窗口大小

我是在删除 sdl2 和 opengl 吗?