【问题标题】:How to avoid memory leak with shared_ptr and SWIG如何使用 shared_ptr 和 SWIG 避免内存泄漏
【发布时间】:2013-09-23 13:32:01
【问题描述】:

我正在尝试使用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?

【问题讨论】:

  • 刷新以查看带有完整、最小示例且易于回答的问题 :)

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


【解决方案1】:

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

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

    这里的解决方法是在你的接口文件中为 std::ofstream 提供一个空定义,以说服 SWIG 它知道足以做更多事情,即使你不打算公开任何成员。

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

因此您的示例变为:

%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')
%}

为了将来的参考,您可以避免使用 %inline 复制仅存在于 .i 文件中的内容:

%inline %{
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() ) );
}
%}

一次性声明、定义和包装所有内容。

【讨论】:

    猜你喜欢
    • 2010-12-22
    • 1970-01-01
    • 1970-01-01
    • 2020-05-13
    • 1970-01-01
    • 2012-10-22
    • 2021-09-09
    相关资源
    最近更新 更多