You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

渲染三角形时触发段错误,是否与着色器源变量相关?

编译无报错但运行段错误的原因分析

编译代码时无报错,但运行触发段错误。问题并非由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),也没编译片段着色器代码。

三、语法错误与内存越界问题

  1. 主程序中的内存越界:

    GLchar infoLog(512);
    

    此处错误地将infoLog定义为单个字符,而非数组。调用glGetShaderInfoLog时会向单个字符的地址写入最多512字节的数据,直接导致内存越界,引发段错误。正确写法应为:

    GLchar infoLog[512];
    
  2. 着色器文件的语法错误:

    • 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个顶点,每个3个float),但配置了两个顶点属性(位置和颜色),步长设为6 * sizeof(GLfloat),导致OpenGL读取顶点数据时越界访问内存。

四、冗余的着色器编译代码

主程序中既初始化了ourShader对象(尝试从文件加载着色器),又手动编译了vertexShaderSource和fragmentShaderSource中的空着色器代码,这部分代码完全冗余,且空着色器无法正常工作。


修复建议

  1. 将Shader ourShader的初始化移至main()函数内,确保在GLFW上下文创建、GLEW初始化完成后再执行。
  2. 补全Shader类构造函数中片段着色器的创建与编译流程,初始化fragment变量。
  3. 修正infoLog的数组定义,修复着色器文件中的语法错误。
  4. 移除主程序中冗余的手动着色器编译代码,统一使用ourShader对象管理着色器。
  5. 调整顶点数据,补充颜色分量,或修改顶点属性配置以匹配现有数据。

代码模块

主程序代码(修复后)

#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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 22:15:53