2015-11-09 59 views
2

在試圖找出如何回答https://stackoverflow.com/questions/33601384/what-is-the-file-descriptor-of-linuxs-environments-standard-logging-stream時,我注意到鏈接到an answer to a related SO post。我用g ++ 4.8.4在上面的鏈接答案中嘗試了代碼,並在程序終止之前得到了分段錯誤。是否有必要重置cout,cerr和clog的rdbuf,如果它們已被更改爲重定向到文件?

這裏的程序:

g++ -Wall -std=c++11 -g socc.cc -o socc 

輸出gdb

GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1 
Copyright (C) 2014 Free Software Foundation, Inc. 
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> 
This is free software: you are free to change and redistribute it. 
There is NO WARRANTY, to the extent permitted by law. Type "show copying" 
and "show warranty" for details. 
This GDB was configured as "x86_64-linux-gnu". 
Type "show configuration" for configuration details. 
For bug reporting instructions, please see: 
<http://www.gnu.org/software/gdb/bugs/>. 
Find the GDB manual and other documentation resources online at: 
<http://www.gnu.org/software/gdb/documentation/>. 
For help, type "help". 
Type "apropos word" to search for commands related to "word"... 
Reading symbols from socc...done. 
(gdb) run 
Starting program: /.........../socc (removed some text here) 
Traceback (most recent call last): 
    File "/usr/share/gdb/auto-load/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19-gdb.py", line 63, in <module> 
    from libstdcxx.v6.printers import register_libstdcxx_printers 
ImportError: No module named 'libstdcxx' 

Program received signal SIGSEGV, Segmentation fault. 
0x000000000040073c in ??() 
(gdb) bt 
#0 0x000000000040073c in ??() 
#1 0x0000000000000000 in ??() 
(gdb) 

我更新程序,以保持老rdbuf

#include <iostream> 
#include <fstream> 

int main() 
{ 
    std::ofstream of("cout.txt"); 
    std::cout.rdbuf(of.rdbuf()); 
    std::cout << "test. test. test." << std::endl; 
    return 0; 
} 

構建程序的命令cout並在專業版結束前將其重置公克。

#include <iostream> 
#include <fstream> 

int main() 
{ 
    std::ofstream of("cout.txt"); 
    auto cout_buff = std::cout.rdbuf(); 
    std::cout.rdbuf(of.rdbuf()); 
    std::cout << "test. test. test." << std::endl; 
    std::cout.rdbuf(cout_buff); 
    return 0; 
} 

通過此更改,程序運行沒有任何問題。

我對cerrclog進行了類似的實驗,結果相同。

這使我的問題:

是否總是必要的,如果他們已被更改爲被重定向到一個文件重置的coutrdbufcerrclog

如果不是,這是g ++缺陷嗎?

回答

5

由尼古拉約祖蒂斯從The C++ Standard Library - A tutorial and reference第二版引用,

章。 13年12月15日,重定向標準流第822

...

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

注意!對象file是本地的,並在塊的末尾被銷燬。這也破壞了相應的流緩衝區。這與「正常」流不同,因爲文件流在構建時分配它們的流緩衝對象並在銷燬時銷燬它們。因此,在這個例子中,cout不能再用於寫入。事實上,它在程序終止時甚至不能被安全銷燬。因此,舊的緩衝區應該隨時保存並恢復!

所以答案似乎是肯定的,即使我沒有標準的報價,上面的作者是相當專家。

+0

非常好找。謝謝。 –

+0

您不一定需要將其換回;問題是'basic_filebuf'的生命週期,如果你沒有把緩衝區改爲別的東西,那麼它的壽命必須超過'cout'。例如,你可以在'std :: cout.rdbuf(nullptr);'末尾執行,而不是保存和恢復原始緩衝區。 –

+0

我注意到標準:*〜ios_base():析構函數不會破壞rdbuf()*。看起來像'〜basic_fstream()'或'〜basic_ofstream()'銷燬相應的'rdbuf()'。 –

相關問題