I am new to your forum, so please forgive any missteps. I am working on a c++ project that reads and writes to a binary file. I first tried doing this using full on c++ but when an error popped up, my instructor told me to use c style file manipulation. Low and behold, I get the same error:
Unhandled exception at 0x6087CCC8 (msvcp110d.dll) in CSI_FinalProj_EmployeeDB.exe: 0xC0000005: Access violation reading location 0x00CDDAEC.
This occurs after successfully completing the read and print, and successfully closing the file. It always occurs when the program exits the function and attempts to return to the calling function. If I put it in the main, it blows up after the return, when the program ends.
The function is a simple print function:
void fileClerkType::printRecord(int id)const
{
FILE* spRead;
employeeType record;
long location;
long size;
location = id - 1;
size = sizeof(employeeType);
spRead = fopen("companyFile.dat", "r");
fseek(spRead, location*size, SEEK_SET);
fread(&record, sizeof(employeeType), 1, spRead);
// If a record has been deleted, the id will be 0
// In that case, don't print
if (record.getEmployeeID() != 0)
{
cout << record << endl;
fread(&record, sizeof(employeeType), 1, spRead);
}
fclose(spRead);
}//Unhandled exception at 0x5065CCC8 (msvcp110d.dll) in
//CSI_FinalProj_EmployeeDB.exe: 0xC0000005: Access violation
//reading location 0x00CDDAEC.
As I said, the function works perfectly. employeeType is a class that has:
2 ints, three strings, and a float
Here is the original c++ version with the same problem. The only difference is that this prints all of the records. It also works perfectly.:
void administratorType::showAllRecords()
{
long test;
long position = 0;
long recordSize = sizeof(employeeType);
ifstream inFile("EmployeesNew.dat", ios::in | ios::binary);
employeeType buffer; // empty employeeType
if(inFile.is_open())
{
inFile.seekg((position * recordSize), ios::beg);
test = inFile.peek(); // Debug
inFile.read(reinterpret_cast<char*>(&buffer), recordSize);
position = 0;
while(position < getRecordCount())
{
inFile.seekg((position * recordSize), ios::beg);
test = inFile.peek();
inFile.read(reinterpret_cast<char*>(&buffer), recordSize);
outputRecord(cout, buffer);
position++;
}
inFile.close();
}
}// Runs fine to here, but throws error when leaving the function
// Unhandled exception at 0x5408CCC8 (msvcp110d.dll) in
// ProjectName.exe: 0xC0000005: Access violation
// reading location 0x0137D3B4.
It has to be an implementation issue. But I cannot see it. Is there something in the implementation that is causing the pointers keeping track of function calls and returns to be corrupted? Thank you in advance for your help.
Sorry, here is the list of member variables for the Employee class. They are not fixed length strings:
int age;
int employeeID; // Auto-generated
float salary;
string lastName;
string firstName;
string ssn;
I created a struct to hold the data being read to the file, then converted all strings to char arrays. Doing each of those did not work, but the combination did. The following is the test program with a main() and a test class (with a struct. This is what I used to find the solution. This is a working program for those of you seeking a way to read/write binary files randomly (unless I screwed it up while formatting it in here).
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
using namespace std;
struct STUDENT
{
char lName[21];
int id;
float sal;
};
class Person
{
public:
struct STUDENT student;
string getlName() const
{
return student.lName;
}
int getID() const
{
return student.id;
}
float getSal() const
{
return student.sal;
}
// Insertion operator
friend std::ostream& operator<<(std::ostream& os, const Person& p)
{
// write out individual members of the struct with
// an end of line between each one
os << p.student.id << ' ' << p.student.lName
<< ' ' << p.student.sal << '\n';
return os;
}
// Extraction operator
friend std::istream& operator>>(std::istream& is, Person& p)
{
// read in individual members of struct
is >> p.student.id >> p.student.lName >> p.student.sal;
return is;
}
Person()
{
}
};
void outputLine( ostream&, const STUDENT&);
int main()
{
char lName[21] = {}; // Extra char for null
int id;
float sal;
int size = sizeof(STUDENT);
string more;
bool exit_now = false;
STUDENT buffer;
Person person;
// In order to randomly access data without destroying the file,
// you must use in and out (read/write mode).
fstream outFile("testFile.dat", ios::in | ios::out | ios::binary);
// Ensure file is opened
if(!outFile)
{
cerr << "Error: Out File could not be opened" << endl;
exit(1);
}
// ************* Random access inserting *************
do
{
cout << "Enter last Name\n?";
cin.getline(lName, 21);
int test;
test = strlen(lName); // FYI: this works to get char count
cout << "Enter salary\n?";
cin >> sal;
cout << "Enter ID\n?";
cin >> id;
strcpy_s(person.student.lName, lName); // copy input to struct
person.student.sal = sal;
person.student.id = id;
cout << person; // object being printed
outFile.seekp((person.student.id - 1) * size);
outFile.write(reinterpret_cast<const char* >(&person.student), size);
// Need this to get the next name
cin.clear();
cin.ignore();
cout << "Do you want to add another record? (yes or no)\n?"
<< endl;
cin >> more;
if (more == "no")
exit_now = true;
// Need this to get the next name properly
cin.clear();
cin.ignore();
}while(exit_now == false);
outFile.close();
// ************* Display Data *************
fstream inFile("testFile.dat", ios::in);
if(inFile) // Is there a connection
{
int target = 0;
int index = 0;
int position;
cout << "All records:" << endl;
while(inFile)
{
inFile.read(reinterpret_cast<char*>(&buffer), size);
if (buffer.id > 0)
{
target = inFile.tellg(); // Debug
cout << buffer.lName << endl;
}
//cout << buffer << endl; // This works
//cout << buffer.id << endl; // This works
}
cout << endl << "Search for a record by id" << endl << endl;
cout << "Enter an id: (0 to exit)" << endl;
cin >> target;
while(target > 0)
{
index = target - 1;
inFile.clear(); // Clear the flags. If the fail flags are
// are set, seekg() will not work.
// Position the file pointer
inFile.seekg(sizeof(Person)*index, ios::beg);
// Read information into the buffer (Person object)
// starting at the file pointer
inFile.read(reinterpret_cast<char*>(&buffer), size);
cout << buffer.lName << endl;
outputLine(cout, buffer);
cout << "Enter an id: (0 to exit)" << endl;
cin.clear();
cin >> target;
}
inFile.close();
cin.clear();
cin.get();
}else
cerr << endl << "Error: Could not complet the file connection."
<< "\nData could not be read."<< endl;
return 0;
}
void outputLine( ostream& output, const STUDENT& record)
{
//output << record << endl; // This works also
output << left << setw(20) << record.lName
<< setw(5) << record.id << setprecision(2)
<< right << fixed << showpoint
<< record.sal << endl;
}