Fstream закрывается после попытки записи без ошибок - PullRequest
0 голосов
/ 18 февраля 2020

Я пишу конфиг для моей программы. Эта конфигурация хранится в формате json с использованием nlohman json. Я использую std :: fstream для записи json объекта в файл. Все было хорошо, но через некоторое время моя программа перестала записывать в файл.
Вот минимальный воспроизводимый пример:

#include <iostream>

#include <nlohmann/json.hpp>
#include <fstream>
#include <iomanip>

bool load(std::fstream &config_fs) {
    if (config_fs) {
        try {
            nlohmann::json json;
            config_fs >> json;
            std::cout << json << std::endl;
            return true;
        } catch (std::exception &e) {
            std::cout << "54 " << (bool)config_fs << std::endl; // 1
            std::cout << "Cannot load config: " << e.what() << std::endl;
            return false;
        }
    }
    std::cout << "Cannot load config because file is not open" << std::endl;
    return false;
}

bool save(std::fstream &config_fs) {
    std::cout <<  "37 " << (bool)config_fs << std::endl;
    if (config_fs) {
        nlohmann::json json{{"test", 42}};
        std::cout <<  "39 " << (bool)config_fs << " " << config_fs.is_open() << " " << strerror(errno) << std::endl;
        config_fs << std::setw(4) << json << std::endl;
        std::cout <<  "41 " << (bool)config_fs << " " << config_fs.is_open() << " " << strerror(errno) << std::endl;
        return true;
    }
    std::cout << "Cannot save config because file is not open" << std::endl;
    return false;
}

int main() {
    std::string config_file = "../config_test.json";
    std::fstream config_fs(config_file, std::ios::in | std::ios::out);
    if (!config_fs) {
        std::cout << "Cannot open configuration file " << config_file <<  ", creating it" << std::endl;
        config_fs.open(config_file, std::ios::out);
        if (!config_fs) {
            std::cout << "Cannot create config file " << config_file << std::endl;
        } else {
            config_fs.close();
            config_fs.open(config_file, std::ios::in | std::ios::out);
        }
    }
    if(!load(config_fs)) {
        std::cout << "Cannot load config from " << config_file << ", putting default values" << std::endl;
        std::cout << "21 " << (bool)config_fs << std::endl;
        save(config_fs);
    }

    return 0;
}

А вот вывод программы:

54 1
Cannot load config: [json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal
Cannot load config from ../config_test.json, putting default values
21 1
37 1
39 1 1 Success
41 0 1 Success

Это означает, что fstream закрывается после моей попытки записи с Success errno и файл остается пустым! Я не знаю, что может вызвать такое поведение. Я также не мог найти подобные вопросы, и я действительно смутился по этому поводу.
Пожалуйста, укажите мне, в чем может быть причина этой проблемы.
Спасибо!

UPD: исключение 'std::ios_base::failure[abi:cxx11]' what(): basic_ios::clear: iostream error было брошено в output_stream_adapter::write_characters(const CharType* s, std::size_t length) после включения исключений для fstream с config_fs.exceptions(std::ios::badbit | std::ios::failbit);

...