2016-04-26 153 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