2013-10-01 104 views
1

以下openGL初學者教程,我已經完成編寫我自己的.OBJ文件的加載程序。寫完之後,通常會進行一個編譯過程,這在C++中是令人厭煩和噁心的。我遇到一個未處理的異常在我的方法之一,這裏是代碼:緩衝區溢出異常通過fscanf_s

float* Loader::LoadObj(const char* filePath){ 
//Declaration of v, vt and vn temporary container buffers for parsing 
vector<glm::vec3> vertcies; 
vector<glm::vec2> uvs; 
vector<glm::vec3> normals; 
vector<fvert> facevertcies; 

//open the file 
FILE* objFile; 
fopen_s(&objFile, filePath,"r"); 
if(objFile == NULL) 
{ 
    printf("Impossible to open the file ! Are you in the right path ?\n"); 
} 

      char line[128]; // where to store the first string read from each line 

      //other containers 
      glm::vec3 vertex; 
      glm::vec2 uv; 
      glm::vec3 normal; 
      fvert fv1,fv2,fv3; 

      // for each line in the obj file 
      while(true) 
      { 

       // read the first word of the line 
       int lineId = fscanf_s(objFile,"%s",line);     
         if (lineId == EOF) 
          break; 
       // parse line by line 
       if (strcmp(line, "v") == 0) 
       { 
         fscanf_s(objFile, "%f %f %f\n", &vertex.x, &vertex.y, &vertex.z); 
         vertcies.push_back(vertex);        
       } 
       else if (strcmp(line, "vt") == 0) 
       {  
         fscanf_s(objFile, "%f %f\n", &uv.x, &uv.y); 
         uvs.push_back(uv);       
       } 
       else if (strcmp(line, "vn") == 0) 
       { 
         fscanf_s(objFile,"%f %f %f\n", &normal.x, &normal.y, &normal.z); 
         normals.push_back(normal); 
       }... //method continues}} 

代碼是不完整的,但它的其他部分是無關緊要的。 LoadObj(char *)方法嘗試打開一個obj文件,然後輸入一個while循環遍歷文件的所有行進行解析。有了斷點,我設法推斷,在循環中fscanf_s的第一次調用時會發生「堆棧緩衝區溢出」異常(文件可以正常打開)。我試圖用空嘗試抓住它,但未成功。

請有人幫助我瞭解是什麼原因導致此異常,並可能通過解決方案補充他們的答案。這是我在這個論壇上的第一篇文章,希望我在這裏沒有違反任何規則。請幫助一個新手。這是CallStack。

XXX.exe!__report_gsfailure(unsigned __int64 StackCookie) Line 147 C 
XXX.exe!__GSHandlerCheckCommon(void * EstablisherFrame, _DISPATCHER_CONTEXT * DispatcherContext, _GS_HANDLER_DATA * GSHandlerData) Line 189 C 
XXX.exe!__GSHandlerCheck_EH(_EXCEPTION_RECORD * ExceptionRecord, void * EstablisherFrame, _CONTEXT * ContextRecord, _DISPATCHER_CONTEXT * DispatcherContext) Line 96 C 
ntdll.dll!000007fc400f9f4d() Unknown 
ntdll.dll!000007fc400fb220() Unknown 
ntdll.dll!000007fc400e4bba() Unknown 
msvcr110d.dll!memset() Line 161 Unknown 
msvcr110d.dll!_input_s_l(_iobuf * stream, const unsigned char * format, localeinfo_struct * plocinfo, char * arglist) Line 939 C++ 
msvcr110d.dll!vfscanf(int (_iobuf *, const unsigned char *, localeinfo_struct *, char *) * inputfn, _iobuf * stream, const char * format, localeinfo_struct * plocinfo, char * arglist) Line 62 C 
msvcr110d.dll!fscanf_s(_iobuf * stream, const char * format, ...) Line 132 C 

加成問題:我還這裏http://blog.markloiseau.com/2012/02/two-safer-alternatives-to-scanf/讀我的代碼可以通過使用字符*,而不是固定char數組和傳遞%毫秒的fscanf,它動態分配存儲器,用於存儲被改善。有人可以告訴我,如何在我的代碼中實現它?這種可能性很有吸引力,儘管事實上我甚至無法讓這個該死的原創遊戲運行起來。感謝那些能夠提供幫助的人。

+0

技術上,的fscanf是不是C++函數。這是一個C函數。你可以使用[iostreams](http://en.cppreference.com/w/cpp/header/iostream)和[getline](http://en.cppreference.com/w/cpp/string/basic_string/getline)而不是'FILE'(和相關功能)。如果我沒有記錯,* .obj是一串由空格分隔的數字/字符串。使用iostreams而不是使用C風格的函數並處理緩衝區溢出會更容易。 – SigTerm

回答

1
int lineId = fscanf_s(objFile,"%s",line); 

可能應改爲:

int lineId = fscanf_s(objFile,"%s",line,sizeof(line)); 

這麼多的安全版本... :)

+0

非常感謝!這工作!有趣的是我之前嘗試過,並沒有。我不認爲這將適用於char *和%ms,因爲它的大小尚未指定。我不能投你的答案,因爲我缺乏聲望點。只要我15歲,我會給你信貸。 – Alxg

+0

謝謝。您應該能夠將其勾選爲「已接受」。 –