2016-04-26 120 views
-2

我想设置一个简单的日志记录系统。打开文件C++

这里是我的Log.h文件

#include <stdlib.h> 
#include <string> 
#include <fstream> 

using namespace std; 

class Log{ 

private: 
    const static string ERROR; 
    const static string WARNING; 
    const static string NOTICE; 
    const static string DEBUG; 
    const static string DEFAULT_FILENAME; 

    static string filename; 
    static ofstream* file; 

public: 
    Log(); 
    Log(string filename); 
    ~Log(); 
    void init(string filename); 

    static void log(string level, string msg); 
    static void error(string msg); 
    static void warning(string msg); 
    static void notice(string msg); 
    static void debug(string msg); 
    static Log* getInstance(); 
}; 

而且在Log.cpp实际代码

#include <stdlib.h> 
#include <string> 
#include "Log.h" 
#include <fstream> 
#include <iostream> 

const string Log::ERROR = "ERROR"; 
const string Log::WARNING = "WARNING"; 
const string Log::NOTICE = "NOTICE"; 
const string Log::DEBUG = "DEBUG"; 
const string Log::DEFAULT_FILENAME = "log.txt"; 

string Log::filename; 
ofstream* Log::file; 

Log::Log(){ 
    this->init(DEFAULT_FILENAME); 
}  

Log::Log(string filename){ 
    this->init(filename); 
}  

Log::~Log(){ 
    this->file->close(); 
}  

void Log::init(string filename){ 
    Log::filename = filename; 
    cout << Log::file << " foo " << Log::filename.c_str() << endl; 
    Log::file->open(filename.c_str(), ios::out | ios::app); 
    cout << "bar" << endl; 
    if(!Log::file->is_open()){ 
      throw 10; 
    } 
} 

void Log::log(string level, string msg){ 
    if(Log::file == NULL) 
      Log(); 
    cout << level << " : " << msg << endl; 
    *Log::file << level << " : " << msg << endl; 
} 

void Log::error(string msg){ 
    log(ERROR, msg); 
} 

void Log::warning(string msg){ 
    log(WARNING, msg); 
} 

void Log::notice(string msg){ 
    log(NOTICE, msg); 
} 

void Log::debug(string msg){ 
    log(DEBUG, msg); 
} 

我主要只包含:

Log::debug("Starting the server"); 

我编译:

g++ -Wall -std=c++11 -c -o main.o main.cpp 
g++ -Wall -std=c++11 -c -o Log.o Log.cpp 
g++ -lfcgi++ -lfcgi main.o Log.o -o main 

当我执行我得到:

0 foo log.txt 
make: *** [exec] Segmentation fault 

的代码段错误打开文件。不知何故,这是不正确的问题,因为此代码:

ofstream myfile; 
myfile.open ("log.txt"); 
myfile << "Writing this to a file.\n"; 
myfile.close(); 

工作得很好。

你知道我为什么得到这个分段错误吗?

谢谢你!

+1

的第一件事,当得到一个错误是在调试器加载它。 – tadman

+3

因为'file'是'NULL'。 –

+0

使用调试器;使用“gdb --args <你的程序>” –

回答

2

我认为问题在于您从未正确创建Log::file。任何指针都必须使用new或一些等效的分配器进行初始化。您在未初始化的指针上调用方法,并且代码在那里崩溃。

您的较小示例工作原因是因为您在堆栈上分配,而不是指向堆对象的指针。无论如何,这是解决这个问题的最好方法。除非您非常小心地管理所有权,否则使用堆分配的对象可能会很匆忙。

这是使用流的一种非常奇怪的方式,您已经有了一个全局的static实例,但您也有一个类。您应该将ofstream实例移动到对象中。

作为风格的问题,没有必要把this->放在每个方法调用或属性引用之前,这就暗示了。这只是在名称冲突的情况下才有必要。

这里的一些想法:做

class Log { 
private: 
    string filename; 
    ofstream file; 
} 

void Log::init(string filename_) { 
    filename = filename_; 

    cout << file << " foo " << filename << ends; 

    file.open(filename.c_str(), ios::out | ios::app); 

    cout << "bar" << std::endl; 

    if(!file.is_open()){ 
     throw 10; 
    } 
} 
+0

我会完成我的单例实现^^谢谢你的回答 – Niilos

+0

这是你的电话。我只是建议你,使用像这样的全局变量会导致难以预料的行为,尤其是在涉及线程时调试非常棘手。 – tadman