C++ 来自文件的着色器,程序停止工作

C++ 来自文件的着色器,程序停止工作,c++,file,opengl,C++,File,Opengl,在一次 在创建顶点着色器的零件中,它使用以下方法 const GLchar* VertexShader = { "#version 330\n"\ "layout(location=0) in vec4 in_Position;\n"\ "layout(location=1) in vec4 in_Color;\n"\ "out vec4 ex_Color;\n"\ "void main(void)\n"\ "{\n"\ "

在一次

在创建顶点着色器的零件中,它使用以下方法

const GLchar* VertexShader =
{
    "#version 330\n"\

    "layout(location=0) in vec4 in_Position;\n"\
    "layout(location=1) in vec4 in_Color;\n"\
    "out vec4 ex_Color;\n"\

    "void main(void)\n"\
    "{\n"\
    "       gl_Position = in_Position;\n"\
    "       ex_Color = in_Color;\n"\
    "}\n"
};
我只是用我的代码替换了这段代码,这段代码从一个文件中引入了着色器

string readShaderFile(string FileName)
{
string ShaderString = "";
ifstream shaderFile;
shaderFile.open(FileName);
    while(!shaderFile.eof())
    {
        string tempholder;
        getline(shaderFile, tempholder);      
        ShaderString.append(tempholder);
        ShaderString.append("\n");
    }
shaderFile.close();

return ShaderString;
}

const GLchar *VertexShader = readShaderFile("v.vert").c_str();

代码不再工作了。可能是什么问题

v.vert文件包含以下代码:

#version 330

layout(location=0) in vec4 in_Position;
layout(location=1) in vec4 in_Color;
out vec4 ex_Color;

void main(void)
{
    gl_Position = in_Position;
    ex_Color = in_Color;
}

您不必将读取的文件拆分为行,只需按原样传递整个文件即可。这些“\n”也在C代码中,因为C字符串中不能有普通换行符。你必须逃离他们。但这不是从文件中读取的必要条件

然后你在这里遇到了一个问题:

const GLchar*VertexShader=readShaderFile(“v.vert”).c_str()

readShaderFile返回一个超出范围的std::string,编译器可能会在那里解串string实例。您必须将返回的字符串存储在它自己的变量中,并且只要您想使用它的c_str(),就必须保持该变量不变

因为这应该是全球范围内的变化,所以如下所示:

static std::string strVertexShader = readShaderFile("v.vert");
GLchar const *VertexShader = strVertexShader.c_str();

加载着色器的函数应如下所示:

string readShaderFile(const string fileName)
{
  std::ifstream shaderFile( fileName.c_str() );

  // find the file size
  shaderFile.seekg(0,std::ios::end);
  std::streampos          length = shaderFile.tellg();
  shaderFile.seekg(0,std::ios::beg);

  // read whole file into a vector:
  std::vector<char>       buffer(length);
  shaderFile.read(&buffer[0],length);

  // return the shader string
  return std::string( buffer.begin(), buffer.end() );
}

临时字符串被销毁,VertexShader包含一个悬空指针。您需要做的是:

const std::string shaderProgram = readShaderFile("v.vert");
const GLchar *VertexShader = shaderProgram.c_str();
// create shader program
// etc

您是否检查了VertexShader的内容以验证它是否被正确读取?是的,打印在控制台中,一切看起来都很好。它类似于c语言,因此应该避免使用空格。只要切换代码,程序就能正常运行。你是说,如果我不将c_str()中的任何内容存储到其他地方,它就会立即丢失。但在这里,我用一个指针指向一些不稳定的东西。这就是为什么const GLchar*VertexShader实际上没有指向任何东西。对吗?@iamcreasy:readShaderFile返回一个std::string,但不能将其保存在变量中。您唯一保留的是指向其.c_str()的指针,该指针只有在返回的std::string实例未被释放时才保持有效。但是,只要调用readShaderFile的作用域离开,该字符串实例就会被释放,c_str()返回的指针就会无效。但是,由于它们位于全局空间,在我的程序终止之前,readShaderFile的返回字符串应该在那里。那么,为什么我要担心失去readShaderFile的作用域呢?全局std::string在哪里?编译器也可以决定放弃std::string实例,因为您从不将其存储在变量中。编译器根本无法从c_str()判断实例是否必须保留——请参阅我的编辑。@iamcreasy:如果函数返回RAII实例,则是!我认为这是常见的C++知识。如果函数本身返回一个指针,那么只保留指针就足够了。当然,除了这个指针,你没有别的东西了。在这种情况下,您可能还需要在某个时候调用指针上的释放。为什么在std::ifstream shaderFile(fileName.c_str())行中使用c_str()@iamcreasy,因为构造函数需要
const char*
请参见
const std::string shaderProgram = readShaderFile("v.vert");
const GLchar *VertexShader = shaderProgram.c_str();
// create shader program
// etc