C++ Unhandled exception when reading file - c++

Trying to write .ply parser to use .ply models in OpenGL.
Trying to begin to read the .ply file and write all the lines of it out.
My program does this but when it print out the last line i get Unhandled exception:
Unhandled exception at 0x62aad540 (msvcr100d.dll) in PLY parser.exe: 0xC0000005: Access violation reading location 0x00000000.
This is my code:
#include <iostream>
#include <fstream>
#include <string>
#include <stdio.h>
using namespace std;
int main ()
{
char buffer[10000];
FILE * myFile;
myFile = fopen("walkman.ply", "r");
if(myFile != NULL)
{
while (!feof(myFile))
{
cout<<fgets(buffer, 10000, myFile);
}
fclose(myFile);
}
else
{
cout<<"file not found"<<endl;
}
system("pause");
return 0;
}
This may be foolish error in my code, but it would be great if someone can spot the error causing this.

Before we get into what the bug is, you should know that the "Unhandled exception ... Access violation reading location 0x00000000" message you get is not caused by a C++ exception; it's the Windows equivalent of "Segmentation fault". Your code tried to dereference the NULL pointer.
Now, you have made one of the classic mistakes in working with FILE objects. feof(fp) does not become true when you reach the end of the file. It only becomes true after you have attempted to read past the end of the file at least once. Thus, your read loop will iterate until after fgets attempts to read past the end of the file. And when fgets attempts to read past the end of the file, it fails, and returns a NULL pointer, which you blindly passed to cout. Kaboom.
(By the way, this is also how istream::eof() works.)
The correct way to write this loop is
while (fgets(buffer, 10000, myFile))
cout << buffer;
(Or, even better, one of these:
while (fgets(buffer, 10000, myFile))
fputs(buffer, stdout));
while(myFile.get(buffer, 10000))
cout << buffer;
it being a little weird to mix stdio.h FILEs and iostreams as you are doing.)

feof() tells you that you've tried to read past the end of file, not that you've reached the end of file. fgets() returns NULL when you're at the end of file and there's no more data to read. That's where the exception is coming from. At the end of file, feof() will return false and fgets() will return NULL, which will cause the exception when your program tries to execute cout << NULL;.
This is the idiomatic way to write it in C style:
char buffer[10000];
FILE* myFile = fopen("walkman.ply", "r");
if (myFile != NULL) {
while (fgets(buffer, sizeof(buffer), myFiles) {
fputs(buffer, stdout);
}
fclose(myFile);
}
or in C++ style:
std::string buffer;
std::ifstream myFile("walkman.ply");
if (myFile.is_open()) {
while (std::getline(myFile, buffer)) {
std::cout << buffer << '\n';
}
}

EDIT: my prognosis was wrong but still read the following if you were meant to use streams.
Also please consider using streams (in ) and vectors, these methods are a lot less error prone and fit in with the C++ style and ethos.
std::ifstream in("walkman.ply", std::ios::binary);
std::vector<char> v(istream_iterator<char>(in),
istream_iterator<char>( ));
or if that is supposed to a string value.
std::ifstream in("walkman.ply");
std::string str(istream_iterator<char>(in),
istream_iterator<char>( ));
std::cout << str << std::endl;

Related

fwrite() writes garbage at the end

I'm trying to write a function that execute a sql file with postgres. Postgres rise me an exception but without specificate the error. So I tryed to rewrite what it read, and I discovery that the file has some garbage at end
stat("treebase.sql",&buf);
dbschema= new (std::nothrow) char[buf.st_size+1];
if(!dbschema)
{
wxMessageBox(_("Not Enough memory"));
return;
}
if( !(fl=fopen("treebase.sql","r")))
{
wxMessageBox(_("Can not open treebase.sql"));
delete []dbschema;
return;
};
fo=fopen("tbout.sql","w");
fread(dbschema,sizeof(char),buf.st_size,fl);
fclose(fl);
dbschema[buf.st_size]='\0';
fwrite(dbschema,sizeof(char),buf.st_size+1,fo);
fflush(fo);
fclose(fo);
and the result is
![screen shot][1]
The input file 150473 length, the output is 156010. I really can not undersand where the 5000 bytes come from.
where is the bug?
[1]: https://i.stack.imgur.com/IXesz.png
You probably can't read buf.st_size much of data, because of the mode of fopen is "r" which defaults to text modes. In text mode fread and fwrite may do some conversions on what you read or write to match the environment special rules about text files such as end of lines. Use "rb" and "wb" modes for fopen for reading and writing binary files as is respectively.
Also, I would rather use fseek and ftell to get the size of file instead of stat.
Here's an example of how you could read the content of the file into memory and then write down an exact copy to another file. I added error checking too to make it clear if anything goes wrong. There's also no need to use stat etc. Plain standard C++ will do.
#include <cerrno>
#include <cstring>
#include <fstream>
#include <iostream>
#include <iterator>
#include <stdexcept>
#include <string>
std::string get_file_as_string(const std::string& filename) {
std::ifstream fl(filename, std::ios::binary); // binary mode
if(!fl) throw std::runtime_error(std::strerror(errno));
// return the content of the whole file as a std::string
return {std::istreambuf_iterator<char>(fl),
std::istreambuf_iterator<char>{}};
}
bool write_string_to_file(const std::string& str, const std::string& filename) {
std::ofstream fo(filename, std::ios::binary);
if(!fo) return false;
// return true or false depending on if it succeeded writing the file:
return static_cast<bool>(fo << str);
}
int main() {
auto dbschema = get_file_as_string("treebase.sql");
// use dbschema.c_str() if you need a `const char*`:
postgres_c_function(dbschema.c_str());
// use dbschema.data() if you need a `char*`:
postgres_c_function(dbschema.data());
if(write_string_to_file(dbschema, "tbout.sql")) {
std::cout << "success\n";
} else {
std::cout << "failure: " << std::strerror(errno) << '\n';
}
}

ifstream.open() not opening file

I've been having a nightmare this evening trying to get some very simple I/O functionality going. As embarrassing as it is, I've had some great help from people on here!
My current issue is that I'm attempting to use ifstream.open() and it simply is not opening the file. This is confirmed by getline(ifstream,line); returning false on it's first call.
Here is a copy paste of the current code:
std::string FSXController::readLine(int offset, FileLookupFlag flag)
{
// Storage Buffer
string line;
streampos sPos(offset);
try
{
// Init stream
if (!m_ifs.is_open())
m_ifs.open("C:\\Users\\guyth\\Documents\\test.txt", fstream::in);
}
catch (int errorCode)
{
showException(errorCode);
return "";
}
// Set stream to read input line
m_ifs.seekg(sPos);
if (!getline(m_ifs, line))
return "";
// Close stream if no multiple selection required
if (flag == FileLookupFlag::single)
m_ifs.close();
return line;
}
This code is in 'bug fix mode' and so therefore is pretty messy, don't worry too much about that, cleanup will happen when this method is finally working.
I have tried:
Absolute file path
Saving path into string and then calling the .c_str() method.
Running VS 2015 in Administrator mode
Ensuring file has read/wright access
Ensuring no duplicate file extensions
Yes the file definitely has content! :D
I'm kinda out of ideas now and am really not sure why this file is refusing to load.
The condition: if (!getline(m_ifs, line)) Repeatedly returns true... :(
EDIT: I've just tried checking m_ifs.fail() immediately after the open and it returns true, so we know the fail flag was triggered :/
Thanks
Guy
Enable exceptions before opening the stream:
m_ifs.exceptions ( std::ifstream::failbit | std::ifstream::badbit );
Otherwise m_ifs.open won't throw.
And you have to catch std::ifstream::failure:
try {
m_ifs.open("C:\\Users\\guyth\\Documents\\test.txt", fstream::in);
}
catch (std::ifstream::failure e) {
std::cerr << "Exception opening file: " << std::strerror(errno) << "\n";
}
See ios::exceptions for more details.

Reading a text file into a char array, then into a char linked list

So currently I am working on an assignment, and for a section of it I need to be able to read a .txt file into a linked list of type char. I was already confused trying to do this, so I set out on a different path and decided to try to copy the text from the file into a char array, and then one by one copy the values in the array into the linked list.
So far I have my program compiling and running up to a certain point, before I receive the error Segmentation fault (core dumped).
The code for reading the file is as follow:
void readFile(list<char> &originList, string fileName){
ifstream fileInput;
fileInput.open(fileName.c_str());
int arraySize = fileInput.gcount();
char tempHold[arraySize];
if (!fileInput) {
cout << "Can't open file: " << fileName << "\n";
} else {
string contents((istreambuf_iterator<char>(fileInput)), istreambuf_iterator<char>());
strcpy (tempHold, contents.c_str());
for (int x = 0; x < fileInput.gcount(); x++) {
originList.push_back(tempHold[x]);
}
}
fileInput.close();
}
Also to add some context, using cout I determined that the code stops running, instead presenting the error, at the following point:
strcpy (tempHold, contents.data());
Also, I am not 100% on how exactly they work, only a loose idea to be honest. I mostly sourced the idea from this Stack Overflow question,
How to copy a .txt file to a char array in c++, but got confused somewhere a long the way.
Thanks in advance for any help you can provide.
istream::gcount returns the number of characters extracted by the last unformatted input operation performed on the object. Since you did not read anything from the file, you should get something wrong.Call, for example, istream.getline(); before calling gcount()
Like my comment to your question says, read each character from the file and add it to the list.
void readFile(list<char> &originList, string fileName) {
ifstream fileInput(fileName.c_str());
if (!fileInput) {
cout << "Can't open file: " << fileName << "\n";
}
char c;
while (fileInput.get(c)) {
originList.push_back(c);
}
}
Note: while (fileInput.get(c)) This reads the character and returns the stream. When a stream is used as a bool value it checks to see if the stream is valid. Valid means eof() and bad() are both false. - From a comment to the answer to the question linked below.
My answer was adapted from this other Stack Overflow question: Reading from text file until EOF repeats last line

When will ofstream::open fail?

I am trying out try, catch, throw statements in C++ for file handling, and I have written a dummy code to catch all errors. My question is in order to check if I have got these right, I need an error to occur. Now I can easily check infile.fail() by simply not creating a file of the required name in the directory. But how will I be able to check the same for outfile.fail() (outfile is ofstream where as infile is ifstream). In which case, will the value for outfile.fail() be true?
sample code [from comments on unapersson's answer, simplified to make issue clearer -zack]:
#include <fstream>
using std::ofstream;
int main()
{
ofstream outfile;
outfile.open("test.txt");
if (outfile.fail())
// do something......
else
// do something else.....
return 0;
}
The open(2) man page on Linux has about 30 conditions. Some intresting ones are:
If the file exists and you don't have permission to write it.
If the file doesn't exist, and you don't have permission (on the diretory) to create it.
If you don't have search permission on some parent directory.
If you pass in a bogus char* for the filename.
If, while opening a device file, you press CTRL-C.
If the kernel encountered too many symbolic links while resolving the name.
If you try to open a directory for writing.
If the pathname is too long.
If your process has too many files open already.
If the system has too many files open already.
If the pathname refers to a device file, and there is no such device in the system.
If the kernel has run out of memory.
If the filesystem is full.
If a component of the pathname is not a directory.
If the file is on a read-only filesystem.
If the file is an executable file which is currently being executed.
By default, and by design, C++ streams never throw exceptions on error. You should not try to write code that assumes they do, even though it is possible to get them to. Instead, in your application logic check every I/O operation for an error and deal with it, possibly throwing your own exception if that error cannot be dealt with at the specific place it occurs in your code.
The canonical way of testing streams and stream operations is not to test specific stream flags, unless you have to. Instead:
ifstream ifs( "foo.txt" );
if ( ifs ) {
// ifs is good
}
else {
// ifs is bad - deal with it
}
similarly for read operations:
int x;
while( cin >> x ) {
// do something with x
}
// at this point test the stream (if you must)
if ( cin.eof() ) {
// cool - what we expected
}
else {
// bad
}
To get ofstream::open to fail, you need to arrange for it to be impossible to create the named file. The easiest way to do this is to create a directory of the exact same name before running the program. Here's a nearly-complete demo program; arranging to reliably remove the test directory if and only if you created it, I leave as an exercise.
#include <iostream>
#include <fstream>
#include <sys/stat.h>
#include <cstring>
#include <cerrno>
using std::ofstream;
using std::strerror;
using std::cerr;
int main()
{
ofstream outfile;
// set up conditions so outfile.open will fail:
if (mkdir("test.txt", 0700)) {
cerr << "mkdir failed: " << strerror(errno) << '\n';
return 2;
}
outfile.open("test.txt");
if (outfile.fail()) {
cerr << "open failure as expected: " << strerror(errno) << '\n';
return 0;
} else {
cerr << "open success, not as expected\n";
return 1;
}
}
There is no good way to ensure that writing to an fstream fails. I would probably create a mock ostream that failed writes, if I needed to test that.

Cout fixes bug in C++ program, but why?

I wrote a simple program to grab stock prices from yahoo finance. The loop that reads the data was truncating early (and ending about where the data from the website shows as opposed to the full download to the correct date for the excell file). So I put in a cout command in the loop to try to debug and voila, it worked correctly!
So why does using the cout function alter the program function? Any ideas? Below is the code. (I found two related posts, but still cant figure it out, e.g. "Can cout alter variables somehow?" and "Weird Error in C++ Program: Removing Printout Breaks Program")
#include <string>
#include <iostream>
#include <fstream>
#include <algorithm>
#include <windows.h>
#include <wininet.h>
using namespace std;
int main()
{
HINTERNET hOpen, hURL;
LPCWSTR NameProgram = L"Webreader"; // LPCWSTR == Long Pointer to Const Wide String
LPCWSTR Website;
char file[101];
int i;
string filename;
unsigned long read;
filename = "data.txt";
ofstream myFile(filename);
if (! myFile)
{
cout < "Error opening file\n";
}
if ( !(hOpen = InternetOpen(NameProgram, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 )))
{
cerr << "Error in opening internet" << endl;
return 0;
}
Website = L"http://ichart.finance.yahoo.com/table.csv?s=MSFT&a=00&b=1&c=2009&d=09&e=22&f=2010&g=d&ignore=.csv";
hURL = InternetOpenUrl( hOpen, Website, NULL, 0, 0, 0 ); //Need to open the URL
InternetReadFile(hURL, file, 100, &read);
file[read] = '\0';
myFile << file;
while (read == 100)
{
InternetReadFile(hURL, file, 100, &read);
file[read] = '\0';
myFile << file;
cout << file; //If I take this line out, the function terminates early.
}
myFile << file;
InternetCloseHandle(hURL);
myFile.close();
return 0;
}
What you have is a "Heisenbug", one which disappears when you try to find it. Make no mistake, the problem is still there and you do need to find it.
The first thing you should be doing is checking the return code of InternetReadFile.
In addition, you should not assume that a successful read will return the full 100 bytes, even if there are more to come. The doco states:
To ensure all data is retrieved, an application must continue to call the InternetReadFile function until the function returns TRUE and the lpdwNumberOfBytesRead parameter equals zero.
: : :
Also, converted lines might not completely fill the buffer, so InternetReadFile can return with less data in lpBuffer than requested.
In other words, I would add:
BOOL rc;
and change your two:
InternetReadFile(hURL, file, 100, &read);
statements to:
rc = InternetReadFile(hURL, file, 100, &read);
then your loop becomes:
while ((!rc) || (read > 0)) // I *think* that's right.
Doing a bit of output probably takes a little time, during which data can arrive from the net, ready to be read by your next call to InternetReadFile.
I haven't used that beast but if it works like other read-functions then it doesn't necessarily read 100 bytes, it may read anything less.
And if so then don't use read == 100 as continuation condition for your loop. Use e.g. read > 0. But do check the documentation, it should tell you what to expect.
Depending on how low-level that function is, it may also be that zero bytes read doesn't mean finished. It might be that you need to check the return value. And e.g. do a little delay before going on.
Cheers & hth.,