2016-11-09 61 views
0

我從std::basic_ostream派生出來,因爲我需要改變創建底層文件緩衝區的方式。 (我需要一個可以查詢的唯一文件名,以便在關閉文件時可以將其刪除;也就是說,不能使用std::tmpnamstd::tmpfile。)我已經對此進行了嘗試(請參見下文),但是我得到了一個分段破壞時的錯誤。破壞派生std :: basic_ostream時出現分段錯誤

什麼導致分段故障?似乎我沒有爲文件緩衝區分配內存,或者我將其刪除了兩次。

// Compile with 
//  clang++ -std=c++14 -stdlib=libc++ main.cpp -o tmpFile 
// 

#include <iostream> 
#include <fstream> 
#include <string> 
#include <streambuf> 

using namespace std; 

template< class charT, class traits=char_traits<charT> > 
class FILE_streambuf : public std::basic_streambuf<charT, traits> { 
public: 
    FILE_streambuf(std::string& filename) 
    { 
     filename = "chicken"; 
     buffer_ = fopen(filename.c_str(), "wx"); 

    } 

    virtual ~FILE_streambuf(){ 
     fclose(this->buffer_); 
    } 
    FILE* buffer_; 
}; 

template< class charT, class traits=char_traits<charT> > 
class tmp_ofstream : public basic_ostream<charT, traits>{ 
public: 
    tmp_ofstream() 
    : filename_("") 
    { 
     try{ 
      this->rdbuf(new FILE_streambuf<charT, traits>(filename_)); 
     } catch (const std::exception& e){ 
      throw e; 
     } 
    } 

    ~tmp_ofstream(){ 
     delete this->rdbuf(); 
     remove(filename_.c_str()); 
    } 
    std::string filename() { return this->filename_; }; 
    std::string filename_; 
}; 

int main(){ 

    tmp_ofstream<char> tmpStream; 
    cout << "tmpStream has filename: " << tmpStream.filename(); 

    cout << "\n-----------------------------------------\n"; 

    return 0; 
} 
+10

因爲你應該*永遠*免費()'你'新'。 'new' - >'delete','malloc' - >'free' –

+0

感謝您的建議。當我將'free'改爲'delete'時,我仍然得到相同的分段錯誤。 :( – jlconlin

+0

提供的源代碼不會產生描述的錯誤,你可以提供更多的細節? –

回答

0

由於Igor Tandetnik has noted代碼隱式調用這是不應該存在的std::basic_ostream默認構造函數。代碼編譯用的libC++,因爲這樣的(保護)默認構造函數作爲擴展:

basic_ostream() {} // extension, intentially does not initialize 

問題消失如果tmp_ofstream的構造函數調用的std::basic_ostream標準認可的構造函數:

tmp_ofstream() 
: basic_ostream<charT, traits>(0) // Sic! 
, filename_("") 
{ 
    try{ 
     this->rdbuf(new FILE_streambuf<charT, traits>(filename_)); 
    } catch (const std::exception& e){ 
     throw e; 
    } 
}