2017-08-08 7 views
1

std::cerrstd::coutの出力をファイルにリダイレクトしたいとします。この目的のために、私はrdbuf関数を以下のコードサンプルのように使用しました。私はstd::coutstd::cerrには何も書いてみるたび残念ながら、私は例外std :: cerrをファイルにリダイレクトしようとするとアクセス違反の例外が発生する

Exception thrown: read access violation. 

*(__imp_std::basic_ios<char,std::char_traits<char> >::rdbuf(...)) was 0xCCCCCCCC. 

を受けます。ここで

は私の問題を生成コードサンプルです:

void redirect() 
{ 
    auto t = std::time(nullptr); 
    auto tm = *std::localtime(&t); 

    std::ostringstream oss; 
    oss << std::put_time(&tm, "%Y-%m-%d_%H-%M-%S.log"); 
    auto cerrFileName = "cerr-" + oss.str(); 
    auto coutFileName = "cout-" + oss.str(); 


    std::ofstream cerrFile(cerrFileName, std::ios::ate); // file is created 
    std::cerr.rdbuf(cerrFile.rdbuf()); 

    std::ofstream coutFile(coutFileName, std::ios::ate); // file is created 
    std::cout.rdbuf(coutFile.rdbuf()); 
} 

int main() 
{ 
    redirect(); 

    std::cout << "Test"; // The exception is thrown here. 

    return 0; 
} 

このサンプルでは、​​それが必要として、2つのファイルを作成しますが、それらのいずれに何も書き込みません。私は間違って何をしていますか?

+1

出力をリダイレクトしているオブジェクトの寿命を考えてみましょう。 – molbdnilo

答えて

3

std::ofstreamは、そのバッファを所有し、std::ofstreamオブジェクトがスコープ外に行くとき、彼らは、バッファに無効なポインタを使用してstd::coutstd::cerrで、その結果、バッファを破壊します。

バッファが時期尚早に削除されないようにしてください。

+0

ルーキーミス。助けてくれてありがとう。 – MxNx

+1

@MxNx間違いは専門知識への唯一の道です! –

2

std::cout.rdbuf(coutFile.rdbuf()); 

あなたはcoutFileとしてstd::coutシェア同じバッファを作る、あなただけのポインタを設定します。

残念ながらstd::basic_streambufは参照カウントされていません。つまり、redirect関数が返ってくると、coutFileは破棄され、閉じられます。これには、バッファオブジェクトの破棄が含まれます。

std::coutに、存在しないバッファオブジェクトへの漂遊ポインタがあります。

バッファオブジェクトを共有するストリームは、完全なプログラムよりも寿命が必要です。 そしてを終了する前に、元のバッファーをstd::coutstd::cerrに復元する必要があります(rdbufは古いバッファーへのポインターを返します)。

+0

これは問題を解決しました。あなたの有益な応答をありがとう。 – MxNx

関連する問題