Hello.

I am writing a program in C++ that is reading some files with fstream then writes with simple function and after that closes them.

I created a struct and i keep there filetag,filepointer and lines. The problem is that from main i can't write or close the file ... but i can acess filetag and lines variables. Here is my code:

struct Fileoutput
{
    string filetag;
    std::fstream* filepointer;
    int lines = 0;
};

static std::vector<Fileoutput> vect_fileoutputs;

static void open_files()
{
    // open all
    struct Fileoutput fo_all;
    fo_all.filetag = "all";
    fo_all.lines = 0;
    std::fstream fs_all;
    fs_all.open("all.log",std::fstream::out | std::fstream::app);
    fo_all.filepointer = &fs_all;
    //*fo_all.filepointer << "something from struct" << endl; // here it is working, in other scope ... no
    vect_fileoutputs.push_back(fo_all);
    /*
    for(const struct Fileoutput fo : vect_fileoutputs)
    {
        *fo.filepointer << "something from vect" << endl; // here is working
    }
    */

    // open error
    struct Fileoutput fo_error;
    fo_error.filetag = "error";
    fo_error.lines = 0;
    std::fstream fs_error;
    fs_error.open("error.log",std::fstream::out | std::fstream::app);
    fo_error.filepointer = &fs_error;
    vect_fileoutputs.push_back(fo_error);
}

static bool write_to_outputfile(char* outputfile,char* content)
{
bool write = false;
for(const struct Fileoutput fo : vect_fileoutputs)
{
    if(strcmp(fo.filetag.c_str(),outputfile) == 0)
    {
        printf("Writing [%s] to [%s]\n",content,outputfile);
        std::fstream* fs_write;
        fs_write = fo.filepointer;
        *fo.filepointer << content; // NOT WORKING ... seg fault
        write = true;
        break;
    }
}

return write;
}

static void close_files()
{
    for(const struct Fileoutput file_output: vect_fileoutputs)
    {
        printf("Closing file [%s]\n",file_output.filetag.c_str());
        std::fstream* fs_temp;
        fs_temp = file_output.filepointer;
        fs_temp->close(); // NOT WORKING ... seg fault
        printf("Closed [%s]\n",file_output.filetag.c_str());
    }
}

int main(int argc, char* argv[])
{
    open_files();

    write_to_outputfile((char*)"all",(char*)"something1\n");
    write_to_outputfile((char*)"all",(char*)"something2\n");
    write_to_outputfile((char*)"all",(char*)"something3\n");

    write_to_outputfile((char*)"error",(char*)"error\n");
    close_files();

    return 1;
}

The gdb error looks like :

gdb error :

Program received signal SIGSEGV, Segmentation fault.
0x0000000000405de9 in ?? ()
(gdb) x 0x0000000000405de9
0x405de9:   0xe8420348
(gdb) x 0x405de9
0x405de9:   0xe8420348
(gdb) x 0xe8420348
0xe8420348: Cannot access memory at address 0xe8420348
(gdb)

What is wrong with the code?

Thank you.

Recommended Answers

All 2 Replies

My first comment is more of an aside, but I was puzzled by the mixing of C stdio and C++ iostreams. I would pick one or the other, not both. Similarly, why use CStrings rather than C++ string objects? It isn't particularly relevant, but it gives the impression that the original coder (you, presumably) was more comfortable with C than C++.

Also, the usual caveats about using globals apply.

Finally, I think there are issues with the entire design of this, starting with why you aren't using a dedicated logging library in the first place. I assume that this is a class assignment, however, meaning that this option is closed to you.

Getting back to the problem at hand, lets look at the first place the segfault is occurring:

static bool write_to_outputfile(char* outputfile,char* content)
{
    bool write = false;
    for(const struct Fileoutput fo : vect_fileoutputs)
    {
        if(strcmp(fo.filetag.c_str(),outputfile) == 0)
        {
            printf("Writing [%s] to [%s]\n",content,outputfile);
            std::fstream* fs_write;
            fs_write = fo.filepointer;
            *fo.filepointer << content; 
            write = true;
            break;
        }
    }

    return write;
}

Here, the problem is that you are attempting to dereference a struct as a pointer. the correct form should be

            fo.*filepointer << content; 

With the indirection operator on the fstream pointer (EDIT: I originally dropped the indirection pointer outright, then noticed that it was still needed on the fstream pointer). I would assume that you've tried that, but sometimes it is the most obvious errors which are hardest to spot - I once spent two weeks chasing a bug which turned out to be two lines which had been swapped. Not fault on your part if you missed it.

The second one is a bit more puzzling, but the solution is even simpler.

static void close_files()
{
    for(const struct Fileoutput file_output: vect_fileoutputs)
    {
        printf("Closing file [%s]\n",file_output.filetag.c_str());
        std::fstream* fs_temp;
        fs_temp = file_output.filepointer;
        fs_temp->close();
        printf("Closed [%s]\n",file_output.filetag.c_str());
    }
}

In this case, the fs_temp variable is entirely unnecessary; you should be able to close the file simply with

        file_output.filepointer->close();

Whether this eliminates the segfault or not, I can't say, but it would at least remove some excess code that might make the solution more confusing.

EDIT: I've just see RProffit's comment, and he has a point, though generally speaking one wouldn't use a pointer to an fstream in the first place, which may affect the issue.

commented: Thanks for this. It does seem to be a curious mix of c and c++. +0
commented: good explination, i want something simple that is why i dont use a log library, and indeed, is a mixing of c and c++, i should rewrite +0
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.