渲染三角形时触发段错误,是否与着色器源变量相关?
编译无报错但运行段错误的原因分析
编译代码时无报错,但运行触发段错误。问题并非由GLchar * fragmentShaderSource和GLchar * vertexShaderSource这两个变量直接导致,核心错误来自以下几处:
一、全局Shader对象提前初始化
全局变量Shader ourShader("core.vs", "core.frag");在main()函数执行前就完成初始化,此时GLFW尚未创建OpenGL上下文、GLEW也未初始化,调用glCreateShader等OpenGL函数会直接触发非法内存访问,这是段错误的主要原因之一。
二、Shader类构造函数的严重错误
在shader.h的构造函数中:
- 声明了
GLuint fragment;但未初始化,直接执行glAttachShader(this->Program, fragment);,fragment是未定义的垃圾值,导致OpenGL尝试绑定无效的着色器对象,触发段错误。 - 完全缺失了片段着色器的创建、编译流程,既没调用
glCreateShader(GL_FRAGMENT_SHADER),也没编译片段着色器代码。
三、语法错误与内存越界问题
主程序中的内存越界:
GLchar infoLog(512);此处错误地将
infoLog定义为单个字符,而非数组。调用glGetShaderInfoLog时会向单个字符的地址写入最多512字节的数据,直接导致内存越界,引发段错误。正确写法应为:GLchar infoLog[512];着色器文件的语法错误:
core.vs中存在多余的引号、语法错误:layout (location = 1) in vec3 color;" // 多余的引号 out vec3 ourColor" // 多余的引号 glPosition = vec 4 (position, 1.0f); // vec4应连写,无空格core.fs中赋值语句错误:color vec4(ourColor, 1.0f); // 缺少赋值运算符=,应为color = vec4(ourColor, 1.0f);
顶点数据与属性配置不匹配:
主程序中顶点数组仅包含位置数据(3个顶点,每个3个float),但配置了两个顶点属性(位置和颜色),步长设为6 * sizeof(GLfloat),导致OpenGL读取顶点数据时越界访问内存。
四、冗余的着色器编译代码
主程序中既初始化了ourShader对象(尝试从文件加载着色器),又手动编译了vertexShaderSource和fragmentShaderSource中的空着色器代码,这部分代码完全冗余,且空着色器无法正常工作。
修复建议
- 将
Shader ourShader的初始化移至main()函数内,确保在GLFW上下文创建、GLEW初始化完成后再执行。 - 补全Shader类构造函数中片段着色器的创建与编译流程,初始化
fragment变量。 - 修正
infoLog的数组定义,修复着色器文件中的语法错误。 - 移除主程序中冗余的手动着色器编译代码,统一使用
ourShader对象管理着色器。 - 调整顶点数据,补充颜色分量,或修改顶点属性配置以匹配现有数据。
代码模块
主程序代码(修复后)
#include <iostream> #define GLEW_STATIC #include "shader.h" #include <GL/glew.h> #include <GLFW/glfw3.h> const GLchar *vertexShaderSource = "#version 330 core\n"; const GLchar *fragmentShaderSource = "#version 330 core\n"; const GLuint WIDTH = 800, HEIGHT = 600; int main() { glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); GLFWwindow *window = glfwCreateWindow(WIDTH, HEIGHT, "Learn OpenGL", nullptr, nullptr); int screenWidth, screenHeight; glfwGetFramebufferSize(window, &screenWidth, &screenHeight); if (nullptr == window) { std::cout << "Failed to create glfw window!\n"; glfwTerminate(); return EXIT_FAILURE; } glfwMakeContextCurrent(window); glewExperimental = GL_TRUE; if (GLEW_OK != glewInit()) { std::cout << "Failed to initialize glew!" << std::endl; return EXIT_FAILURE; } glViewport(0, 0, screenWidth, screenHeight); // 修复:移至上下文初始化后 Shader ourShader("core.vs", "core.frag"); GLint success; GLchar infoLog[512]; // 修复:改为数组 GLfloat vertices[] = { // 位置 // 颜色 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f }; GLuint VBO, VAO; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // 位置属性 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0); glEnableVertexAttribArray(0); // 颜色属性 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); glEnableVertexAttribArray(1); glBindVertexArray(0); while (!glfwWindowShouldClose(window)) { glfwPollEvents(); glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); ourShader.Use(); glBindVertexArray(VAO); glDrawArrays(GL_TRIANGLES, 0, 3); glBindVertexArray(0); glfwSwapBuffers(window); } glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); glfwTerminate(); return EXIT_SUCCESS; }
shader.h代码(修复后)
#ifndef SHADER_H #define SHADER_H #include <GL/glew.h> #include <fstream> #include <iostream> #include <sstream> #include <string> class Shader { public: GLuint Program; Shader(const GLchar *vertexPath, const GLchar *fragmentPath) { std::string vertexCode; std::string fragmentCode; std::ifstream vShaderFile; std::ifstream fShaderFile; vShaderFile.exceptions(std::ifstream::badbit); fShaderFile.exceptions(std::ifstream::badbit); try { vShaderFile.open(vertexPath); fShaderFile.open(fragmentPath); std::stringstream vShaderStream, fShaderStream; vShaderStream << vShaderFile.rdbuf(); fShaderStream << fShaderFile.rdbuf(); vShaderFile.close(); fShaderFile.close(); vertexCode = vShaderStream.str(); fragmentCode = fShaderStream.str(); } catch (std::ifstream::failure e) { std::cout << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ" << std::endl; } const GLchar *vShaderCode = vertexCode.c_str(); const GLchar *fShaderCode = fragmentCode.c_str(); GLuint vertex, fragment; GLint success; GLchar infoLog[512]; // 顶点着色器编译 vertex = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertex, 1, &vShaderCode, NULL); glCompileShader(vertex); glGetShaderiv(vertex, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(vertex, 512, NULL, infoLog); std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED" << infoLog << std::endl; } // 修复:添加片段着色器编译 fragment = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragment, 1, &fShaderCode, NULL); glCompileShader(fragment); glGetShaderiv(fragment, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(fragment, 512, NULL, infoLog); std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED" << infoLog << std::endl; } // 链接程序 this->Program = glCreateProgram(); glAttachShader(this->Program, vertex); glAttachShader(this->Program, fragment); glLinkProgram(this->Program); glGetProgramiv(this->Program, GL_LINK_STATUS, &success); if (!success) { glGetProgramInfoLog(this->Program, 512, NULL, infoLog); std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl; } glDeleteShader(vertex); glDeleteShader(fragment); } void Use() { glUseProgram(this->Program); } }; #endif
core.fs代码(修复后)
#version 330 core in vec3 ourColor; out vec4 color; void main() { color = vec4(ourColor, 1.0f); }
core.vs代码(修复后)
#version 330 core layout (location = 0) in vec3 position; layout (location = 1) in vec3 color; out vec3 ourColor; void main() { glPosition = vec4(position, 1.0f); ourColor = color; }
内容的提问来源于stack exchange,提问作者user11677215
相关产品推荐
相关产品推荐

