如何使用shared_ptr和SWIG避免内存泄漏

时间:2013-09-18 17:03:28

标签: c++ python file-io memory-leaks swig

我正在尝试使用boost::shared_ptr来允许我在我的python脚本中使用c ++文件I / O流对象。但是,生成的包装器警告我它正在泄漏内存。

这是一个显示问题的最小.i文件:

%module ptrtest

%include "boost_shared_ptr.i"
%include "std_string.i"

%shared_ptr( std::ofstream )

%{
#include <fstream>
#include <boost/shared_ptr.hpp>

typedef boost::shared_ptr< std::ofstream > ofstream_ptr;

ofstream_ptr mk_out(const std::string& fname ){
    return ofstream_ptr( new std::ofstream( fname.c_str() ) );
}

%}

ofstream_ptr mk_out(const std::string& fname );


%pythoncode %{

def leak_memory():
    ''' demonstration function -- when I call
        this, I get a warning about memory leaks
    ''''
    ostr=mk_out('/tmp/dont_do_this.txt')


%}

这是警告:

In [2]: ptrtest.leak_memory()
swig/python detected a memory leak of type 'ofstream_ptr *', no destructor found.

有没有办法修改.i文件告诉界面如何正确处理shared_ptr?

1 个答案:

答案 0 :(得分:9)

您的示例缺少两部分来运行析构函数:

  1. 由于SWIG对std::ofstream一无所知,因此默认行为除了传递不透明句柄外什么都不做。有关此内容的进一步讨论,请参阅another answer of mine

    此处的修复是在您的界面文件中为std::ofstream提供一个空的定义,以说服SWIG它知道做得更多,即使您不打算公开任何成员。

  2. SWIG需要查看typedef本身 - 在%{ %}内部,它只是直接传递给输出模块,而不是在包装本身中使用。

  3. 因此,您的示例变为:

    %module ptrtest
    
    %include "boost_shared_ptr.i"
    %include "std_string.i"
    
    %shared_ptr( std::ofstream )
    
    namespace std {
      class ofstream {
      };
    }
    
    %{
    #include <fstream>
    #include <boost/shared_ptr.hpp>
    
    typedef boost::shared_ptr< std::ofstream > ofstream_ptr;
    
    ofstream_ptr mk_out(const std::string& fname ){
        return ofstream_ptr( new std::ofstream( fname.c_str() ) );
    }
    %}
    
    typedef boost::shared_ptr< std::ofstream > ofstream_ptr;
    ofstream_ptr mk_out(const std::string& fname );
    
    %pythoncode %{
    def leak_memory():
        ostr=mk_out('/tmp/dont_do_this.txt')
    %}
    

    为了将来参考,您可以避免重复只包含{.1}} .i文件的内容:

    %inline

    一次性声明,定义和包装它。