Norhan Foda Norhan Foda - 2 months ago 8
C++ Question

string iterator is not dereferencable

I am using a library to parse .pgn file, and when I tried to run the project I found this error:Debug Assertion Failed! program: C:\windows\SYSTEM32\MSVCP110D.dll File: c:\program files (x86)\microsoft visual studio 11.0\vc\include\xstring
Line:79
Expression:string iterator not dereferencable
For information on how your program can cause an assertion failure, see the visual C++ documentation on asserts.

the problem is that when the iterator reaches to the end of the file, it points to nothing (start iterator (itr1) == end iterator (itr2)), I tried to add conditions to check if itr1 reached to the end of the file but it was useless.
So please tell me where is my fault.
here is my code source.cpp file:

#include <iostream>
#include <fstream>
#include <PGNGameCollection.h>
int main()
{
std::ifstream pgnfile("sample.pgn");
pgn::GameCollection games;
pgnfile >> games;
std::cout << "the file sample.pgn contains " << games.size() << "games" << std::endl;
system("pause");
return 0;
}


and here is the class function that causes the error:

bool pgn::Parser::getComment(std::string::const_iterator &itr1, const std::string::const_iterator &itr2, pgn::CommentText &out)
{
std::string::const_iterator local_itr=itr1;
std::string comment;
if(*local_itr != '{')
return false;
local_itr++; //skipping '{'

while((*local_itr != '}') && (local_itr != itr2))
{
comment += *local_itr++;
}
local_itr++; //skipping '}'
skipBlanks(local_itr, itr2);
itr1=local_itr;
out=pgn::CommentText(comment);
return true;
}


I have searched stackoverflow and google for all similar problems but I could not find the answer. also I traced the code line by line until I have reached to the function that caused the error.

AnT AnT
Answer

If itr2 is your end-iterator, then you must check your iterator for the end-condition before trying to dereference it

while((local_itr != itr2) && (*local_itr != '}'))

You are doing it the other way around, which would definitely lead to the problem you described.

It might also make sense to add checks for end-condition at the very beginning of your function, since there you are also dereferencing local_itr.

Also, if your cycle terminated because local_itr reached itr2, and there's nothing at itr2 and after it, then the code after the cycle makes no sense. You are not allowed to increment local_itr in that situation.