如何避免shared_ptr和SWIG的内存泄漏 [英] How to avoid memory leak with shared_ptr and SWIG

查看:1464
本文介绍了如何避免shared_ptr和SWIG的内存泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图使用 boost :: shared_ptr 允许我在我的python脚本中使用c ++文件I / O流对象。



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

 %module ptrtest 

%includeboost_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():
''演示函数 - 当我调用
this,I获取有关内存泄漏的警告
'''
ostr = mk_out('/ tmp / dont_do_this.txt')


%}

以下是警告:

  In [2]:ptrtest.leak_memory()
swig / python检测到'ofstream_ptr *'类型的内存泄漏,找不到析构函数。

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

解决方案

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


  1. 由于SWIG完全不了解 std :: ofstream 默认行为是除了通过一个不透明句柄之外什么都不做。有关这方面的进一步讨论,请参见我的另一个答案



    此处的修复是为您的接口文件中的 std :: ofstream 提供一个空定义,以说服SWIG


  2. SWIG需要查看typedef本身 - 在<$ c $




因此你的例子成为:

 %module ptrtest 

% boost_shared_ptr.i
%includestd_string.i

%shared_ptr(std :: ofstream)

命名空间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')
%}

为了将来的参考,你可以避免重复的东西,只存在.i文件与%inline

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

它声明,定义和


I'm trying to use boost::shared_ptr's to allow for me to use c++ file I/O stream objects in my python script. However, the generated wrapper warns me that it is leaking memory.

Here's a minimal .i file exhibiting the problem:

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


%}

Here's the warning:

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

Is there a way to modify the .i file to tell the interface how to dispose of the shared_ptr properly?

解决方案

Your example is missing two parts to get the destructor to run:

  1. Since SWIG knows absolutely nothing about std::ofstream the default behaviour is to do nothing beyond pass an opaque handle around. See another answer of mine for a further discussion of this.

    The fix here is to supply an empty definition for std::ofstream in your interface file to convince SWIG it knows enough to do more, even if you don't plan on exposing any members.

  2. SWIG needs to see the typedef itself - inside the %{ %} it just gets passed straight to the output module, not used in the wraping itself.

Thus your example becomes:

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

For future reference you can avoid duplication of stuff that lives only in the .i file with %inline:

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

Which declares, defines and wraps it all in one shot.

这篇关于如何避免shared_ptr和SWIG的内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆