2016-04-26 5 views
-2

シンプルなログシステムを設定しようとしています。ファイルを開くセグメンテーションフォールトC++

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

私が使用してコンパイル:

ここ

は私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); 
} 

私の主のみが含まれています

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

関連する問題