Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I can access a static fstream from one file only

I need to use a static fstream in multiple source files. However I can only use it from a single file and not from the others. Furthermore, its use in the other files does not give any error, it just does nothing.

This is the code:

/// log.h
#ifndef LOG_H
#define LOG_H
#include <fstream>
static std::ofstream ofs;
#define LOG(level) ofs << level << ": "
#endif

/// test.cpp
#include "log.h"
#include "other.h"
int main()
{
   ofs.open("file.log");
   LOG(5) << "Test log 1" << std::endl;      // OK
   OtherFunc();
}

/// other.h
#ifndef OTHER_H
#define OTHER_H
extern int OtherFunc();
#endif

/// other.cpp
#include "other.h"
#include "log.h"
int OtherFunc()
{
   LOG(5) << "Test log 2" << std::endl;      // Nothing
}

This is the generated file:

5: Test log 1

Thank you!

Platform:
Linux
g++ 4.5.1

like image 693
Pietro Avatar asked Dec 20 '25 04:12

Pietro


2 Answers

Static global variables: variables declared as static at the top level of a source file (outside any function definitions) are only visible throughout that file ("file scope", also known as "internal linkage"). The default storage class for global variable is extern which has external or whole program linkage. So if you want to use the global variable in multiple files it must be extern.

like image 64
Forever Learner Avatar answered Dec 22 '25 18:12

Forever Learner


static here means you're explicitly asking the compiler to give the file-scope variable std::ofstream ofs static linkage, which means it is visibly only in the current file.

The twist is that you're doing this in a header, which means every .cpp file including the header gets its own distinct instance of std::ofstream ofs. Only because you've given it static linkage can they all have distinct file-scope variables with the same name - otherwise there would be a name clash.

So, in main.cpp, you open your local ofs and write to it. In other.cpp, you have your own local copy of ofs, but never open it ... so the output doesn't go anywhere, and certainly not to file.log.


The other answers are correct, that changing the header declaration to extern std::ofstream ofs; will allow all the .cpp files to share a single object called ofs, and then you just need to put the instance in exactly one place (main.cpp would be fine).

It might be simpler, and cleaner, to make the LOG(level) an out-of-line function call though; then the output stream could live in a log.cpp with the function definition, and nobody else needs to see it.

like image 39
Useless Avatar answered Dec 22 '25 18:12

Useless