Search code examples
c++pointersstructreferencestream

How to use ofstream as a part of struct - arg of function


I am trying to use ofstream, opened in function getlog() in function WriteLine(). I have a structure named LOG:

struct LOG {
    wchar_t logfile[PARM_MAX_SIZE];
    std::ofstream* stream;
};

which is an argument of function WriteLine(). When I am trying to use this stream, there is an error of reading.

I am trying to use a reference on a LOG variable. I tried to convert ofstream* stream to ofstream& but I don't know how to do it properly, because initialization of a LOG is:

static const LOG INITLOG {L"", NULL};

and I don't know how to change it to use a reference on a stream.

Functions:

LOG getlog(wchar_t logfile[]) {
    ofstream logf(logfile, ios::app);
    if (!logf.is_open()) {
        throw ERROR_THROW(112)
    }
    LOG log{};
    wcscpy_s(log.logfile, logfile);
    log.stream = &logf;
    return log;
}

void WriteLine(LOG log, char* c, ...) {
    char str[80]{};
    char** p = &c;
    while (*p[0]) {
        strcat_s(str, *p);
        p++;
    }
    str[strlen(str)] = '\0';
    ofstream* logf = log.stream;
    *logf << "str";
}

main function

int _tmain(int argc, wchar_t* argv[]) {
    setlocale(LC_ALL, "rus");
    Log::LOG log = Log::INITLOG;
    try {
        Parm::PARM parms = Parm::getparm(argc, argv);
        log = Log::getlog(parms.log);
        Log::WriteLine(log, (char*)"Тест:", (char*)" без ошибок \n", "");
        /*Log::WriteLine(log, (wchar_t*)L"Тест:", (wchar_t*)L" без ошибок \n", L"");
        Log::WriteLog(log);*/
    }
    catch (Error::ERROR e) {
        cout << "Ошибка " << e.id << ": " << e.message << ", строка " << e.inext.line << ", позиция " << e.inext.col << endl << endl;
    }

    system("pause");
    return 0;
}

Solution

  • Your getlog() function is creating a new stream and returning it, but is doing so by returning a pointer to a local variable that goes out of scope when the function exits. To avoid that, you will need to create the stream dynamically instead, eg:

    struct LOG {
        std::wstring logfile;
        std::unique_ptr<std::ofstream> stream;
    };
    
    LOG getlog(const wchar_t* logfile) {
        LOG log;
        log.logfile = logfile;
        log.stream = std::make_unique<std::ofstream>(logfile, std::ios::app);
        if (!log.stream->is_open()) {
            throw ERROR_THROW(112)
        }
        return log;
    }
    
    template<typename... Args>
    void WriteLine(LOG& log, Args&&... args) {
        (*(log.stream) << ... << args) << '\n';
    }
    
    int _tmain(int argc, wchar_t* argv[]) {
        setlocale(LC_ALL, "rus");
        try {
            Parm::PARM parms = Parm::getparm(argc, argv);
            Log::LOG log = Log::getlog(parms.log);
            Log::WriteLine(log, "Тест:", " без ошибок ");
            /*Log::WriteLine(log, L"Тест:", L" без ошибок ");
            Log::WriteLog(log);*/
        }
        catch (Error::ERROR e) {
            cout << "Ошибка " << e.id << ": " << e.message << ", строка " << e.inext.line << ", позиция " << e.inext.col << endl << endl;
        }
    
        std::system("pause");
        return 0;
    }