【问题标题】:Access violation reading from random access file in c++从 C++ 中的随机访问文件读取访问冲突
【发布时间】:2012-06-12 03:00:41
【问题描述】:

我正在制作的这部分程序应该打印出存储在随机访问二进制文件中的所有记录。每次我运行它,它都会打印出所有的记录,然后抛出一个访问冲突异常:

void readFile()
{
    ifstream inFile("hardware.txt", ios::in | ios::binary);

    if(!inFile)
    {
        cerr<<"File could not be opened."<<endl;
        exit(1);
    }

    cout<<left<<setw(10)<<"Account"<<setw(16)
            <<"Name"<<setw(11)<<"Quantity"<<left<<setw(10)<<"Price"<<endl;

    Hardware File;

    inFile.read(reinterpret_cast<char *>(&File), sizeof(Hardware));

    while(inFile && !inFile.eof())
    {
        if(File.getAccountNumber() != 0)
            outputLine(cout, File);

        inFile.read(reinterpret_cast<char *>(&File), sizeof(Hardware));
    }
}

澄清一下,“硬件”是存储在 Hardware.h 中的一个类。

硬件.h

#ifndef HARDWARE_H
#define HARDWARE_H

#include <string>
using std::string;

class Hardware
{
public:
Hardware (int = 0, string = "", int = 0, double = 0);

void setAccountNumber(int);
int getAccountNumber() const;

void setName(string);
string getName() const;

void setAmount(int);
int getAmount() const;

void setPrice(double);
double getPrice() const;
private:
int accountNumber;
string name;
int amount;
double price;
};

#endif

硬件.cpp

#include <string>
using std::string;

#include "hardware.h"

Hardware::Hardware(int accountNumberValue, string nameValue, int amountValue, double priceValue)                            

{
setAccountNumber(accountNumberValue);
setName(nameValue);
setAmount(amountValue);
setPrice(priceValue);
}

void Hardware::setAccountNumber(int accountValue)
{
accountNumber = accountValue;
}

int Hardware::getAccountNumber() const
{
return accountNumber;
}

void Hardware::setName(string nameValue)
{
name = nameValue;
}

string Hardware::getName() const
{
return name;
}

void Hardware::setAmount(int amountValue)
{
amount = amountValue;
}

int Hardware::getAmount() const
{
return amount;
}

void Hardware::setPrice(double priceValue)
{
price = priceValue;
}

double Hardware::getPrice() const
{
return price;
}

【问题讨论】:

  • 如何定义inFileFile(和Hardware)?现在你的代码看起来一点意义都没有——即使在最好的情况下你所拥有的也很丑陋。访问冲突听起来像是您可能超出了缓冲区(很可能当您读入File 时,就好像它是一个字符数组一样)。只有四行代码肯定有太多的“WTF”(哦,你的循环控制显然也是错误的)。
  • 我把剩下的功能放上来,应该澄清一下(虽然,可能还有很多“wtf”)。
  • 从文件中读取 C++ 对象的原始字节是一个非常糟糕的主意——它几乎总是未定义的行为并导致崩溃。你是怎么定义Hardware的?
  • 你不能像那样读(或写)std::string。你应该阅读serialization
  • @JoachimPileborg 哪一行有问题?此外,它的读取(和写入)很好,只是它似乎超出了文件的边界。虽然所有数据都打印出来了......

标签: c++ file random binary access-violation


【解决方案1】:

正如 Joachim 所说,您不能像那样读入 std::string

它不是一个值类型;在内部,它将保存一个指向包含其文本的内存区域的指针。如果您从文件中读取随机二进制块,则该字符串指针可能指向任何地方;取消引用它(例如,通过获取或设置 'name' 的值)可能会引发访问冲突或段错误等。

我会添加几个新方法,像这样(不保证编译或工作!​​):

void Hardware::Serialise(std::ostream& stream) const
{
  stream << accountName << "\n" << accountNumber << "\n" << accountValue << std::endl;
}
void Hardware::Deserialise(std::istream& stream)
{
  char[1024] buffer;
  stream.readsome(buffer, 1024);
  accountName = buffer;
  buffer >> accountNumber >> accountValue;
}

了解对象的内部结构是正确(反)序列化它的关键。处理失败条件、记录间分隔符以及使用字符串流而不是固定大小的缓冲区来读取名称,留给读者作为练习。

【讨论】:

  • 答案中添加了简单示例。
猜你喜欢
  • 2014-12-23
  • 2018-08-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-08
相关资源
最近更新 更多