【问题标题】:String getting corrupted when reading from file从文件读取时字符串损坏
【发布时间】:2014-09-26 21:09:36
【问题描述】:

我正在使用 OpenGL 进行一些实验,并且正在尝试加载着色器。它需要 const char* 中的源代码,但由于我在 C++ 上执行此操作,我可以使用 std::strings 然后调用 str.c_str()。这不是问题 - 当我尝试读取文件时,它读取完美,但返回的值是损坏的字符串。这是代码的相关部分:

// inline method on engine.hpp
inline void readFile(std::string filePath, std::string* retValue) 
{
std::ifstream file;
file.open(filePath);

std::string result;

std::string line;
while (!file.eof())
{
    std::getline(file, line);
    result.append(line + "\n");
}

    memcpy(retValue, &result, sizeof(result));
}

// implemented method on engine.cpp
GLint Engine::createShader(std::string vs, std::string fs)
{
GLuint vertex = glCreateShader(GL_VERTEX_SHADER);
GLuint fragment = glCreateShader(GL_FRAGMENT_SHADER);

std::string vsSourceStr = "";
std::string fsSourceStr = "";

readFile(vs, &vsSourceStr);
readFile(fs, &fsSourceStr);

const char* vsSource = vsSourceStr.c_str();
const char* fsSource = fsSourceStr.c_str();

//std::string t_vs = readFile(vs);

//const char* vsSource = readFile(vs).c_str();
//const char* fsSource = readFile(fs).c_str();

glShaderSource(vertex, 1, &vsSource, NULL);
glCompileShader(vertex);

glShaderSource(fragment, 1, &fsSource, NULL);
glCompileShader(fragment);

GLint program = glCreateProgram();
glAttachShader(program, vertex);
glAttachShader(program, fragment);
glLinkProgram(program);

if (shaderCompiled(program))
{
    std::cout << "shader successfully compiled" << std::endl;
}
else
{       
    std::cout << "shader not compiled" << std::endl;
    printShaderError(vertex);
    printShaderError(fragment);

    std::cout << "Vertex Shader source:" << std::endl;
    std::cout << vsSource << std::endl;

    std::cout << "Fragment Shader source:" << std::endl;
    std::cout << fsSource << std::endl;
}

return program;
}

这是 Visual Studio 在调试时所说的:http://prntscr.com/4qlnx7

它完美地读取文件,只是使返回值崩溃。正如您在我的代码中看到的那样,我已经尝试使用引用和复制内存来返回结果。 还是谢谢。

【问题讨论】:

标签: c++


【解决方案1】:

这不会像你想的那样:

std::string line;
while (!file.eof())
{
    std::getline(file, line);
    result.append(line + "\n");
}

请使用:

std::string line;
while (std::getline(file, line))
{
    result.append(line + "\n");
}

原因是eof() 直到文件被读取后才被触发。这意味着您的 std::getline() 可能已失败(在 EOF)并且您正在使用该错误数据。

请参阅: C++ FAQ 15.5 关于 eof()

【讨论】:

    【解决方案2】:

    当您执行memcpy(retValue, &amp;result, sizeof(result)); 时,您正在复制内部 std::string 结构,而不是字符串数据。改为分配字符串:*retValue = result

    在 readFile() 中使用结果字符串的引用将获得更健壮的版本:

    void readFile(std::string filePath, std::string& retValue) 
    {
        std::ifstream file(filePath);
    
        retValue.clear();
    
        std::string line;
        while (std::getline(file, line))
        {
            retValue += line;
            retValue += '\n';
        }
    }
    
    GLint Engine::createShader(std::string vs, std::string fs)
    {
        GLuint vertex = glCreateShader(GL_VERTEX_SHADER);
        GLuint fragment = glCreateShader(GL_FRAGMENT_SHADER);
    
        std::string vsSourceStr;
        std::string fsSourceStr;
    
        readFile(vs, vsSourceStr);
        readFile(fs, fsSourceStr);
        // ...
     }
    

    其他将文件读入字符串的方法是使用std::istreambuf_iterator:

    inline std::string readFile(std::string const& filename)
    {
        std::ifstream file(filename);
        std::istreambuf_iterator<char> begin(file), end;
        return std::string(begin, end);
    }
    

    【讨论】:

    • 谢谢!我不知道std::istreambuf_iterator,非常有用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-12
    • 1970-01-01
    • 2011-01-22
    相关资源
    最近更新 更多