From: Oleg S. <se...@ma...> - 2002-01-28 05:42:29
|
Wu Yongwei wrote: > > Hi all, especially Alexandros and Danny, I suppose I have found the problem > at last. > > Let's trace it step by step. > > First, I merged code from Alexandros's and that from stdc++ source: > > --------BEGIN testio.cpp -------- > #include <iostream> > #include <fstream> > #include <string> > #include <errno.h> > > using namespace std; > > long getCleanSize(ifstream &ifs) > { > long cnt=0; > string curs; > > int w = ifs.width (0); > if (ifs.ipfx0 ()) > { > register streambuf *sb = ifs.rdbuf (); > curs.resize (0); > while (1) > { > int ch = sb->sbumpc (); > if (ch == EOF) > { > ifs.setstate (ios::eofbit); > break; > } > else if (string_char_traits<char>::is_del (ch)) > { > sb->sungetc (); > break; > } > curs += static_cast<char> (ch); > if (--w == 1) > break; > } > } > > ifs.isfx (); > if (curs.length () == 0) > ifs.setstate (ios::failbit); > > cout<<curs.size()<<" bytes IN\n"; > > if (ifs.eof()) > cerr<<"EOF\n"; > else if (ifs.fail()) > cerr<<ifs.rdstate()<<"\n"; > return cnt; > } > int main(int argc,char **argv) > { > ifstream ifs(argv[1], ios::in | ios::binary); > cout<<getCleanSize(ifs); > } > --------END testio.cpp -------- > > Gdb showed that the problems lies in the line with "is_del(ch)". In fact, it > is a call to "isspace". The following program will show the real problem: > > -------- BEGIN testisspace.cpp -------- > #include <ctype.h> > #include <stdio.h> > > int main() > { > int a = 244, b = 245; > printf("%d\n", isspace(a)); > printf("%d\n", isspace(b)); > printf("%d\n", isspace(a - 256)); > printf("%d\n", isspace(b - 256)); > return 0; > } > -------- END testisspace.cpp -------- > > A compliant C++ compiler should output four 0's. Visual C++ and Cygin GCC > do. MinGW will output "0 0 0 8" or "0 0 8 8". > > Who has time to fix this? > Visual C++ outputs "0 0 0 8" if program compiled without debugging information. Thus problem is in msvcrt: isspace called with parameter which is negative, and code in isspace doesn't convert it into char or unsigned before using array of symbol information so indexes are out of bounds. So fix is to change stl like this >> else if (string_char_traits<char>::is_del ( static_cast<char> (ch) )) Oleg Sesov. |