std :: ifstream由于某种原因关闭了吗?

时间:2017-08-18 02:02:30

标签: c++

我正在尝试打开包含文件数据的ifstreams,可以在以后读取。我试图将ifstreams的向量传递给构造函数,但由于某种原因,当我遍历向量时,所有引用都被关闭。但是,其他变量(数据流和元流)仍然是开放的。

我在这里缺少什么?我来自一个非常沉重的Java背景,所以我还在学习C ++

FileStore.h

//
// Created by Tom on 8/16/2017.
//

#ifndef CFS_FILESTORE_H
#define CFS_FILESTORE_H

#include <fstream>
#include <list>
#include "ByteBuffer.h"

class FileStore {

private:
    std::ifstream *data_stream;
    std::vector<std::ifstream *> index_streams;
    std::ifstream *meta_stream;

public:
    FileStore(std::ifstream *data, std::vector<std::ifstream *> indexes, std::ifstream *meta);
    ~FileStore() = default;

    int get_type_count();
    ByteBuffer read(int type, int id);
    int get_file_count(int type);

    static FileStore open(std::string &root);
};


#endif //CFS_FILESTORE_H

FileStore.cpp

//
// Created by Tom on 8/16/2017.
//

#include "FileStore.h"

FileStore::FileStore(std::ifstream *data, std::vector<std::ifstream *> indexes, std::ifstream *meta)
        : data_stream(data), index_streams(std::move(indexes)), meta_stream(meta) {

    std::cout << std::boolalpha << "Data Open : " << data_stream->is_open() << std::endl;
    std::cout  << "Meta Open : " << meta_stream->is_open() << std::endl;

    for (auto v : index_streams) {
        std::cout << "Index Open : " << v->is_open() << std::endl;
    }
}

int FileStore::get_type_count() {
    return 0;
}

ByteBuffer FileStore::read(int type, int id) {
    return ByteBuffer();
}

int FileStore::get_file_count(int type) {
    return 0;
}

FileStore FileStore::open(std::string &root) {
    std::ifstream data(root + "main_file_cache.dat2");
    if (!data.good())
        throw std::runtime_error("data file does not exist.");

    std::vector<std::ifstream *> indexes;
    for (int i = 0; i < 254; i++) {
        std::ifstream index(root + "main_file_cache.idx" + std::to_string(i));
        if (!index.good())
            break;

        indexes.push_back(&index);
    }

    std::ifstream meta(root + "main_file_cache.idx255");
    if (!meta.good())
        throw std::runtime_error("meta file does not exist.");

    return FileStore(&data, indexes, &meta);
}

输出

Data Open : true
Meta Open : true
Index Open : false
Index Open : false
Index Open : false
Index Open : false
Index Open : false
Index Open : false
Index Open : false
Index Open : false
Index Open : false
Index Open : false
Index Open : false
Index Open : false
Index Open : false
Index Open : false
Index Open : false
Index Open : false
Index Open : false
Index Open : false
Index Open : false
Index Open : false
Index Open : false
Index Open : false
Index Open : false
Index Open : false
Index Open : false
Index Open : false
Index Open : false
Index Open : false

2 个答案:

答案 0 :(得分:2)

    std::ifstream index(root + "main_file_cache.idx" + std::to_string(i));

这构造了一个std::ifstream对象。它以自动范围声明。

    indexes.push_back(&index);
}

这会将指向std::ifstream的指针推送到indexes向量中,但由于index的自动作用域会立即结束,所以index对象会立即生效销毁,相应的文件被关闭。您在内部循环内的自动作用域中声明了此std::ifstream对象。因此,对象在循环结束时被破坏。

然后,后续代码尝试取消引用存储在indexes向量中的指针,这些指针现在都是悬空指针。这会导致未定义的行为。

此外,indexes向量通过值传递,这导致向量被复制,这增加了混乱。

您需要重新阅读C ++手册中的以下章节:

  • 解释自动范围以及动态范围如何在C ++中工作的章节。

  • 这一章解释了通过引用传递函数参数和按值传递它们之间的区别,以及这意味着什么。

答案 1 :(得分:0)

每个index在其范围的末尾被销毁,使得它们的指针无效

std::vector<std::ifstream *> indexes;
for (int i = 0; i < 254; i++) {
    std::ifstream index(root + "main_file_cache.idx" + std::to_string(i));
    if (!index.good())
        break;

    indexes.push_back(&index);
} // index is destroyed here

您应该更改它以使用new创建它们(只需确保在您完成后删除它们)

std::vector<std::ifstream *> indexes;
for (int i = 0; i < 254; i++) {
    std::ifstream* index = new std::ifstream(root + "main_file_cache.idx" + std::to_string(i));
    if (!index->good())
        break;

    indexes.push_back(index);
}

或更好,请改用std::vector<std::unique_ptr<std::ifstream>>std::make_unique

当您从meta返回时,dataopen可能会遇到同样的问题。