2013-10-01 4 views
1

После обучения openGL beginner, я закончил писать свой собственный загрузчик файлов .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/, что мой код может быть улучшена за счет использования полукокса * вместо фиксированного массив символов и прохождения% мс 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

Спасибо. Вы должны уметь указывать его как «принятый». –

Смежные вопросы