2018年10月22日 星期一

C++的IO在跨平台時的問題

C++的IO在跨平台時的問題

前言

  最近將C++的繪圖引擎從Windows轉到Linux,本想問題比較大的應該是OpenGL的部分,但結果是我花在OpenGL的部分的時間沒想像的多,反倒是其它的問題讓我花了很多時間Debug,而這個問題跟C++的IO有關,以下是Debug的過程,在此做個紀錄。

內容

  在繪圖引擎轉到Linux後,花了些時間解決OpenGL在跨平台的問題,接著本想就沒什麼大問題了,但實際上卻是Shader的部分卻在Run的時候初始化失敗,本想是程式的工作目錄的問題,但結果並不是,Debug後發現檔案是有讀到的,但Shader的初始化這段程式碼在Windows跑的時候都沒問題,難道Shader的初始化有分平台!?

  在此說明一下,在我的繪圖引擎的Shader初始化是將檔案讀入後,在經由Parser取得Shader的資訊後,再將shader code送進OpenGL的API。Debug後發現問題發生在Parser取得Shader的資訊的過程,由於這個Parser做得有點複雜,所有我花了大量的時間在Debug這個Parser,在Debug時候一直有個想法,不就是個Parser,為什麼Windows與Linux的結果會不一樣?最後我找到兇手了,兇手來自以下的程式碼
std::string shaderCode;
std::ifstream fileStream(shaderFilePath);
if(!fileStream)
  return false;
shaderCode.assign((std::istreambuf_iterator<char>(fileStream) ),std::istreambuf_iterator<char>() );
//start parse
//...


return true;

這段程式碼將檔案讀入後送到Parser,但我發現"shaderCode"的內容在Windows與Linux的結果是不一樣的!由於Shader檔案是在Windows的文字編輯器打的,所以換行的字元是"\r\n",這段程式碼在VC(visual c++)跑的時候會將'\r'過濾掉,但是在g++的時候卻不會,所以造成之後的Parser會Parse出不同的結果,造成初始化錯誤。

  所以要如何解決這個問題呢?解決的方法並不是改變這段讀取檔案的程式碼,因為如果這樣解決的話代表Parser本身不容許'\r'在字尾,所以比較好的解法是讓Parser不要單單使用Split的方式來取得,而是在每次Split後也同時做Trim的動作,這樣就可以讓Parser接受有\r'的內容了。

參考資料

How to read line by line or a whole text file at once?

沒有留言:

張貼留言