Fragment shader doesn't always compile

Hello there. I’m totally new to OpenGL so I hope to be as clear as possible. I’m currently following the Learn OpenGL guide and I’ve reached the Shaders chapter (I don’t know why but I can’t add links because otherwise I can’t post the topic). I decided to make my own version of the Shader class that you can find at the end of the chapter. Jumping directly to the .cpp file, this is my own version:

#include "./shader.hpp"
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>

customlib::Shader::Shader(const char* vertexPath, const char* fragmentPath)
{
	const char* vertexShaderSource;
	const char* fragmentShaderSource;

	customlib::Shader::m_ReadShaderFiles(&vertexShaderSource, &fragmentShaderSource, vertexPath, fragmentPath);
	
	uint32_t vertexID;
	uint32_t fragmentID;
	customlib::Shader::m_CompileShader(vertexID, GL_VERTEX_SHADER, vertexShaderSource);
	customlib::Shader::m_CompileShader(fragmentID, GL_FRAGMENT_SHADER, fragmentShaderSource);

	customlib::Shader::m_GenerateShaderProgram(ID, vertexID, fragmentID);

	glDeleteShader(vertexID);
	glDeleteShader(fragmentID);
}

void customlib::Shader::Use() { glUseProgram(ID); }

void customlib::Shader::SetUniformBool(const char* name, bool value) const
{
	int uniformReference = glGetUniformLocation(ID, name);
	glUniform1i(uniformReference, (int)value);
}

void customlib::Shader::SetUniformInt(const char* name, int value) const
{
	int uniformReference = glGetUniformLocation(ID, name);
	glUniform1i(uniformReference, value);
}

void customlib::Shader::SetUniformFloat(const char* name, float value) const
{
	int uniformReference = glGetUniformLocation(ID, name);
	glUniform1f(uniformReference, value);
}

uint32_t customlib::Shader::GetID() { return ID; }

void customlib::Shader::m_ReadShaderFiles(const char** outVertShaderSource, const char** outFragShaderSource, const char* vertexPath, const char* fragmentPath)
{
	std::string vertexCode;
	std::string fragmentCode;

	std::ifstream vShaderFile;
	std::ifstream fShaderFile;
	vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
	fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);

	try
	{
		// Vertex Shader                           // Fragment Shader
		vShaderFile.open(vertexPath);              fShaderFile.open(fragmentPath);

		std::stringstream vShaderStream;           std::stringstream 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_SUCCESFULLY_READ" << std::endl;
	}
	*outVertShaderSource = vertexCode.c_str();
	*outFragShaderSource = fragmentCode.c_str();
}

void customlib::Shader::m_CompileShader(uint32_t& shaderID, GLenum shaderType, const char* shaderSource)
{
	shaderID = glCreateShader(shaderType);
	glShaderSource(shaderID, 1, &shaderSource, NULL);
	glCompileShader(shaderID);

	int compileStatus;
	char infoLog[512];
	glGetShaderiv(shaderID, GL_COMPILE_STATUS, &compileStatus);
	if (!compileStatus)
	{
		glGetShaderInfoLog(shaderID, 512, NULL, infoLog);
		std::cout << "ERROR::SHADER_ID::" << shaderID << "::COMPILATION_FAILED\n" << infoLog << std::endl;
	}
}

void customlib::Shader::m_GenerateShaderProgram(uint32_t& shaderProgramID, uint32_t vertex, uint32_t fragment)
{
	shaderProgramID = glCreateProgram();

	glAttachShader(shaderProgramID, vertex);
	glAttachShader(shaderProgramID, fragment);

	glLinkProgram(shaderProgramID);

	int linkStatus;
	char linkInfoLog[512];
	glGetProgramiv(shaderProgramID, GL_LINK_STATUS, &linkStatus);

	if (!linkStatus)
	{
		glGetProgramInfoLog(shaderProgramID, 512, NULL, linkInfoLog);
		std::cout << "ERROR::SHADER_PROGRAM::" << shaderProgramID << "::LINKING_FAILED\n" << linkInfoLog << std::endl;
	}
}

(where obviously customlib is my namespace).

I guess that the problem is probably related to the <fstream> and <sstream> libraries, because I get this error like 25% of the time randomly:

This is really weird because I also made my code to print what the ifstream read and there were no syntax errors. I don’t know why this happens, it’s just so random and annoying. Most of the times I have to excecute my project like 3 times before getting no error, without changing a single thing in my code

This is my fragment shader by the way:

#version 330 core

out vec4 FragColor;
in vec3 ourColor;

void main()
{
   FragColor = vec4(ourColor, 1.0);
}

This is a basic C++ error. You returned a pointer to the contents of a std::string that’s on the stack. Because it’s on the stack, it will be destroyed when the function returns. Thus, the calling function receives a pointer to destroyed memory.

Debugging builds tend to write bad data to such memory, so that you immediate get errors.

But why this happens only with the fragment shader? What should I do to improve this? Should I use std::string instead of const char* for both vertex and fragment shader source?

Edit: I’ve made some changes in my code according the problem you mentioned and got rid of those const char** and instead passed two std::string references in m_ReadShaderFiles() and this seems to work perfectly fine without errors. This is what I did:

void customlib::Shader::m_ReadShaderFiles(std::string& outVertShaderSource, std::string& outFragShaderSource, const char* vertexPath, const char* fragmentPath)
{
	std::ifstream vShaderFile;
	std::ifstream fShaderFile;
	vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
	fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);

	try
	{
		// Vertex Shader                                 // Fragment Shader
		vShaderFile.open(vertexPath);                    fShaderFile.open(fragmentPath);
												         
		std::stringstream vShaderStream;                 std::stringstream fShaderStream;
		vShaderStream << vShaderFile.rdbuf();            fShaderStream << fShaderFile.rdbuf();
												         
		vShaderFile.close();                             fShaderFile.close();

		outVertShaderSource = vShaderStream.str();       outFragShaderSource = fShaderStream.str();
	}
	catch (std::ifstream::failure e)
	{
		std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl;
	}
}

Thank you so much