从二进制文件读取后,当控制返回到调用函数时未处理的异常

时间:2015-11-20 00:59:31

标签: c++ c file-handling unhandled-exception

我是您论坛的新手,所以请原谅任何失误。我正在研究一个读写二进制文件的c ++项目。我首先尝试在c ++上使用完全执行此操作,但是当弹出错误时,我的导师告诉我使用c样式文件操作。低,看哪,我得到同样的错误:

CSI_FinalProj_EmployeeDB.exe中0x6087CCC8(msvcp110d.dll)的未处理异常:0xC0000005:访问冲突读取位置0x00CDDAEC。

成功完成读取和打印并成功关闭文件后会发生这种情况。它总是在程序退出函数并尝试返回调用函数时发生。如果我把它放在主体中,它会在返回后在程序结束时爆炸。

该功能是一个简单的打印功能:

2015-11-20 11:37:25,764 DEBUG [DBxHnFjViCgLYgYb-IrfqQ] com.pingidentity.pa.core.interceptor.flow.InterceptorFlowController:148 - Invoking request handler: Scheme Validation for Request to [pagateway:5000] [/]
2015-11-20 11:37:25,764 DEBUG [DBxHnFjViCgLYgYb-IrfqQ] com.pingidentity.pa.core.interceptor.flow.InterceptorFlowController:200 - Exception caught.  Invoking abort handlers
com.pingidentity.pa.sdk.policy.AccessException: Invalid request protocol.
    at com.pingidentity.pa.core.interceptor.SchemeValidationInterceptor.handleRequest(SchemeValidationInterceptor.java:61)

正如我所说,该功能完美无缺。 employeeType是一个具有以下内容的类:

2个整数,三个字符串和一个浮点数

以下是具有相同问题的原始c ++版本。唯一的区别是这会打印所有记录。它也很完美。:

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.

这必须是一个实施问题。但我看不到它。实现中是否存在导致指针跟踪函数调用和返回被破坏的内容?提前感谢您的帮助。

对不起,这是Employee类的成员变量列表。它们不是固定长度的字符串:

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.

1 个答案:

答案 0 :(得分:0)

std::string不是trivially copyable类型,因此没有一个作为成员的类也可以轻易地复制。

您不能像这样以字节方式读取或写入非平凡的可复制类型。由于大多数库已采用SSO(假设lastNamefirstNamessn足够短),从字符串读取时函数可能不会崩溃,但是你'在破坏期间仍会遇到问题。

在c ++中序列化数据的规范方法是重载流操作符,这是一个例子:

std::istream& operator>>(std::istream& stream, employeeType& employee)
{
  return stream >>
    employee.age        >>
    employee.employeeID >>
    employee.salary     >>
    employee.lastName   >>
    employee.firstName  >>
    employee.ssn;
}

std::ostream& operator<<(std::ostream& stream, employeeType const& employee)
{
  return stream <<
    employee.age        << ' ' <<
    employee.employeeID << ' ' <<
    employee.salary     << ' ' <<
    employee.lastName   << ' ' <<
    employee.firstName  << ' ' <<
    employee.ssn        << '\n';
}

可以使用类似

的循环读取或写入记录
for (employeeType e; inFile >> e;)
  //do something with e

或者您甚至可以使用

将它们复制到矢量中
std::vector<employeeType> employees(
  std::istream_iterator<employeeType>(inFile),
  std::istream_iterator<employeeType>()
);