2014-09-26 114 views
1

我正在做一些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

它讀取文件完美,只是崩潰的返回值。我已經嘗試過使用引用和複製內存來返回結果,就像你在代碼中看到的那樣。 無論如何,謝謝。

+0

可能的重複[爲什麼iostream :: eof內循環條件被認爲是錯誤的?](http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered -wrong) – 2014-09-26 21:15:22

+1

您正在使用memcpy複製到std :: s特靈,這是完全錯誤的。只需返回文件內容,就完成了。無論如何,IO可能需要比可能複製字符串更長的時間。 – 2014-09-26 21:29:07

回答

3

這不會做你認爲:

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()

+0

它工作!非常感謝你。 – EduRenesto 2014-09-26 21:19:21

0

當你做memcpy(retValue, &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); 
} 
+0

謝謝!我不知道std :: istreambuf_iterator,非常有用。 – EduRenesto 2014-09-28 21:18:16