【问题标题】:Segmentation fault when destructing a derived std::basic_ostream破坏派生的 std::basic_ostream 时出现分段错误
【发布时间】:2016-11-09 16:22:25
【问题描述】:

我从std::basic_ostream 派生,因为我需要更改创建底层文件缓冲区的方式。 (我需要一个可以查询的唯一文件名,以便在文件关闭时可以将其删除;即,不能使用std::tmpnamstd::tmpfile。)我已经尝试过(见下文),但是我在销毁时遇到分段错误。

导致分段错误的原因是什么? 似乎我没有为文件缓冲区分配内存,或者我将其删除了两次。

// 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;
}

【问题讨论】:

  • 因为你应该永远 free()newnew -> delete, malloc -> free
  • 感谢您的建议。当我将 free 更改为 delete 时,我仍然遇到相同的分段错误。 :(
  • 提供的源代码没有产生描述的错误,你能提供更多细节吗?
  • 你为什么在~tmp_ofstream() 中调用remove( filename_.c_str() );
  • std::basic_ostream 不应该有默认构造函数。目前还不清楚你的程序是如何编译的。让它tmp_ofstream() : filename_(""), basic_ostream&lt;charT, traits&gt;(nullptr)seems to work for me

标签: c++ c++11 segmentation-fault libc++


【解决方案1】:

作为Igor Tandetnik has noted,代码隐式调用了不应该存在的std::basic_ostream 的默认构造函数。代码使用 libc++ 编译,因为 the latter provides 这样的(受保护的)默认构造函数作为扩展:

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;
    }
}

【讨论】:

    猜你喜欢
    • 2016-07-11
    • 1970-01-01
    • 2020-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多