【问题标题】:C++ clear vector of structs exception结构异常的 C++ 清除向量
【发布时间】:2018-05-16 14:06:25
【问题描述】:

我定义了一个名为 Part 的结构:

struct Part
{
    std::string id;
    double area;
    double volume;

    bool operator==(const Part& part) const
    {
        return (area == part.area) && (volume == part.volume);
    }

    bool operator!=(const Part& part) const
    {
        return !operator==(part);
    }

    bool operator<(const Part &part) const
    {
        return (area + volume) < part.area + part.volume;
    }
};

我创建了一个零件向量并将该向量保存在一个二进制文件中。 然后我将二进制文件读入向量。我确认所有零件都正确读入向量。我读取二进制文件的功能是:

static bool restore_vector_from_file(const char* fileName, std::vector<Part> &parts) {

    std::ifstream instream(fileName, std::ios::in | std::ios::binary);

    if (!instream) {
        return false;
    }

    instream.seekg(0, instream.end);
    int bytes = instream.tellg();
    instream.seekg(0, instream.beg);

    int vector_size = bytes / sizeof(Part);
    parts.resize(vector_size);
    instream.read(reinterpret_cast<char*>(parts.data()), bytes);

    if (!instream) 
    {
        return false;
    }

    instream.close();
    return true;
}

我的主要功能是:

int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        std::cout << "Number of arguments must be 3" << std::endl;
        return 1;
    }

    // Load parts with properties to a vector
    const char* folderName = argv[1];
    const char* vectorFileName = argv[2];

    std::vector<Part> partArray;

    // Load from pre-saved file to save time
    if (!restore_vector_from_file(vectorFileName, partArray))
    {
        std::cout << "Failed to retore vector from file" << std::endl;
        return 1;
    }
    partArray.clear();
    return 0;
}

在我尝试清除 partArray 之前一切正常。它抛出一个异常:

Exception thrown: read access violation.
_Pnext was 0x1BC586CCB48.

即使我删除partArray.clear()return 0; 时也会抛出同样的异常

请帮忙。

【问题讨论】:

    标签: c++ vector ifstream


    【解决方案1】:

    您的结构Part 不是POD type 也不是trivial,因此您无法像以前那样保存或加载它。

    以它的id 成员为例,std::string 对象通常包含一个 指针,这是保存的内容。该指针在任何其他进程中均无效。

    您需要使用serialization 来保存和加载您的结构。

    【讨论】:

    • 成为PODtrivial 在这里并没有任何意义。您可以轻松地构造一个无法以相同方式(反)序列化的 POD 类型。 IE。 struct Foo { int *bar; };顺便说一句,值得一提的是“pod”定义已被弃用。
    【解决方案2】:
    instream.read(reinterpret_cast<char*>(parts.data()), bytes);
    

    这是一个很大的代码气味和 UB。 std::string 持有一个指向堆分配字符串的指针(模 SSO),但是当您尝试 reinterpret_cast 它形成文件时(假设您以相同的方式保存它)您只会得到一些垃圾值(因为它现在不指向任何有效的内存位置),因此当std::string 尝试在析构函数中释放它时,它会像您所经历的那样失败。你根本无法在这里做你想做的事情。

    我建议你为你的结构重载istream&amp; operator&gt;&gt; (istream&amp; is, Part&amp; p);。 ostream 对应的&lt;&lt; 也是如此。这应该很容易,因为所有 Part 字段都已存在此类重载。

    【讨论】:

      猜你喜欢
      • 2012-10-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-16
      • 1970-01-01
      • 2011-02-12
      • 2012-02-18
      相关资源
      最近更新 更多