Luc Moussiegt
Luc Moussiegt

Reputation: 13

ofstream.open() set failbit in DLL called by UWP application

I've looked up on Internet to see if someone encountered that problem, but haven't found anything.

So I'm trying to use a C++ DLL in a C# UWP application. This DLL has a log file which is opened at the beginning of the code with the following function:

#include <string>
#include <iostream>

using namespace std;

int Logger::set(string file_name, bool clear_log) {
    _file_stream.exceptions(ofstream::failbit | ofstream::badbit);
    try {
        _file_stream.open(file_name, ios_base::out | (clear_log ? ios_base::trunc : ios_base::app));
    }
    catch (ofstream::failure) {
        return -1;
    }
    _file_stream << "";
    return 0;
}

Here is the code of the Logger class:

class Logger {
private:
    std::ofstream _file_stream;

public:
    Logger() {};
    ~Logger() { _file_stream.close(); };

    int set(std::string file_name, bool clear_log);
}

Now, this code works fine when I use the DLL in standalone mode. But when called via the UWP app, the open() function throws an ofstream::failure exception saying:

ios_base::failbit set: iostream stream error

I first thought this was due to UWP's weird access rights policies, but after debugging, file_name points to the correct package folder in AppData, so it should be okay to write a file here.

What could be the problem?

EDIT: I found out that for some reason, the C file API works as expected. That is, the following code successfully creates the file:

#include <iostream>
using namespace std;

int Logger::set(string file_name, bool clear_log) {
    FILE* test = fopen(file_name.c_str(), clear_log ? "w" : "a");
    if(!test)
    {
        return -1;
    }
    fprintf(test, "");
    return 0;
}

Upvotes: 0

Views: 149

Answers (1)

Luc Moussiegt
Luc Moussiegt

Reputation: 13

I figured out myself after some more active debugging. Somewhere before in the code this similar (indirect) call to ofstream::open didn't fail:

ofstream out("out.txt", ios_base::trunc);

And by putting breakpoints on the right place, I was able to determine that in that case, the value of the open mode (the ios_base::trunc argument) resolved to 18 (the expected value), whereas it resolved to the weird value 1594 in the problematic case, when using the ternary operator.

Replacing the ternary operator by a if-else block resolved the problem:

int Logger::set(string file_name, bool clean_log) {
    _file_stream.exceptions(ofstream::failbit | ofstream::badbit);
    try
    {
        if (clean_log)
            _file_stream.open(file_name, ios_base::trunc);
        else
            _file_stream.open(file_name, ios_base::app);
    }
    catch (ofstream::failure)
    {
        return -1;
    }
    return 0;
}

Upvotes: 0

Related Questions