将Python脚本封装成MFC的DLL,发生内存泄漏

yuanyingtanxi 2009-03-17 07:23:00
将Python脚本封装成MFC的DLL

=============================ScriptEngine.cpp =============================

#include "stdafx.h"
#include <afxdllx.h>

#include "PythonEngine.h"

#ifdef _MANAGED
#error Please read instructions in ScriptEngine.cpp to compile with /clr
// If you want to add /clr to your project you must do the following:
// 1. Remove the above include for afxdllx.h
// 2. Add a .cpp file to your project that does not have /clr thrown and has
// Precompiled headers disabled, with the following text:
// #include <afxwin.h>
// #include <afxdllx.h>
#endif

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


static AFX_EXTENSION_MODULE ScriptEngineDLL = { NULL, NULL };

#ifdef _MANAGED
#pragma managed(push, off)
#endif

extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
// Remove this if you use lpReserved
UNREFERENCED_PARAMETER(lpReserved);

if (dwReason == DLL_PROCESS_ATTACH)
{
TRACE0("ScriptEngine.DLL Initializing!\n");

// Extension DLL one-time initialization
if (!AfxInitExtensionModule(ScriptEngineDLL, hInstance))
return 0;

// Insert this DLL into the resource chain
// NOTE: If this Extension DLL is being implicitly linked to by
// an MFC Regular DLL (such as an ActiveX Control)
// instead of an MFC application, then you will want to
// remove this line from DllMain and put it in a separate
// function exported from this Extension DLL. The Regular DLL
// that uses this Extension DLL should then explicitly call that
// function to initialize this Extension DLL. Otherwise,
// the CDynLinkLibrary object will not be attached to the
// Regular DLL's resource chain, and serious problems will
// result.

new CDynLinkLibrary(ScriptEngineDLL);

}
else if (dwReason == DLL_PROCESS_DETACH)
{
TRACE0("ScriptEngine.DLL Terminating!\n");

// Terminate the library before destructors are called
AfxTermExtensionModule(ScriptEngineDLL);
}
return 1; // ok
}

#ifdef _MANAGED
#pragma managed(pop)
#endif


=============================PythonEngine.cpp =============================
#include "StdAfx.h"
#include "PythonEngine.h"
#include <Python.h>
CPythonEngine::CPythonEngine(void)
{
Py_Initialize();
}

CPythonEngine::~CPythonEngine(void)
{
Py_Finalize();
}
BOOL CPythonEngine::Execute(CString strScriptName)
{
return TRUE;
}


环境XP SP2+VS2005+Python3.01
这个DLL在其它程序里调用时发生大量的内存泄漏,怎么回事尼
...全文
614 27 打赏 收藏 转发到动态 举报
写回复
用AI写文章
27 条回复
切换为时间正序
请发表友善的回复…
发表回复
twelvewind 2010-02-20
  • 打赏
  • 举报
回复
[python-win32] Memory Leak in MFC/C++ based Python Extended/Embedded code.

http://mail.python.org/pipermail/python-win32/2008-January/006615.html

有没有解决的方法啊,这个问题掩蔽了我自己造成的泄漏,调试很麻烦啊
twelvewind 2010-02-20
  • 打赏
  • 举报
回复
http://mail.python.org/pipermail/python-bugs-list/2004-September/025262.html


I am seeing the same behavior. The leaks only appear when
the VC++6.0 project is linking to one of the Multithreaded
DLL runtime libraries - which occurs when you use MFC as a
shared DLL. If the project is linking to one of the
Multithreaded non-DLL runtime libraries - which occurs when
you use MFC as a static library, the memory leaks do not appear.

临时用静态链接的方法解决。
fibbery 2009-03-19
  • 打赏
  • 举报
回复
听起来有点像stl的内存管理方式。申请后,重复利用。
yuanyingtanxi 2009-03-19
  • 打赏
  • 举报
回复
是这样啊
看来Python还是有问题呀
算了,不封DLL了,还是写成宏吧
killbug2004 2009-03-19
  • 打赏
  • 举报
回复
Python does allocate memory that is never freed - but in general, that is
not a "leak", just a 1-time allocation that lives for the life of the
program. However, if you *repeatedly* call Py_Initialize/Finalize, I
believe some leaks will happen, and I believe there is an open bug report in
the Python tracker regarding this (but don't have the time to find it).

Assuming you just want to init and finalize once, then you can safely ignore
the MFC leak check output. Something like 'valgrind' does differentiate
between leaks and 1-time allocations, so if you *really* need a leak
checker, you should be looking at something like that.

老外说可以忽略。。。。

google 关键字 python vc memory leak
yuanyingtanxi 2009-03-19
  • 打赏
  • 举报
回复
昨晚试了下Python2.61,同样的代码、同样的内存泄漏

奇怪,大家都是怎么用的呢,怎么没人提过这方面的问题呢
killbug2004 2009-03-18
  • 打赏
  • 举报
回复
有个老贴中讲用boost库

在c++中使用python最好借助boost库,以下为例子代码

#include <python.h>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/python/object.hpp>
#include <boost/python/list.hpp>
#include <boost/python/class.hpp>
#include <string>
using namespace std;
using namespace boost::python;


/**
python 解释器单件初始化类
*/
class PyInitT
{
public:
static PyInitT& init()
{
static PyInitT obj;
return obj;
}

virtual ~PyInitT() { Py_Finalize(); }

protected:
PyInitT() { Py_Initialize();}
};

object CallPythonFunction(const char* module, const char* function)
{
PyInitT::init(); // initialize python

object mod( (handle<>(borrowed(PyImport_ImportModule((char*)module)) )) );
object names = mod.attr("__dict__");
object result((handle<>(
PyRun_String(function,Py_eval_input, names.ptr(),names.ptr()))
));
return result;
}

list<int> ReadFileIntoBuf(string filename)
{
boost::python::list pyret = extract<boost::python::list>(
CallPythonFunction("ReadFileIntoBuf",filename.c_str()) );

list<int> ret;
for( int i=0; i<pyret.len(); i++ ) ret.push_back( extract<int>( pyret[i] );

return ret;
}
yuanyingtanxi 2009-03-18
  • 打赏
  • 举报
回复
Debug时跟踪的呗
我下了Python3.01的源码,并且编译了Python30_d.lib所以可以Debug的
fibbery 2009-03-18
  • 打赏
  • 举报
回复
你试怎么确定Py_Finalize();函数被调用了?
yuanyingtanxi 2009-03-18
  • 打赏
  • 举报
回复
to:killbug2004
我用的是3.01,并不是3.1
killbug2004 2009-03-18
  • 打赏
  • 举报
回复
Python 3.1 是alpha版 建议现在不要用 用3.0吧
yuanyingtanxi 2009-03-18
  • 打赏
  • 举报
回复
to:fibbery
单独运行EXE,没有内存泄漏
把Execute函数注释掉,有内存泄漏
把DLL的构造和析构中的Py_Initialize();Py_Finalize();注释掉,没有内存泄漏
也就是说用了Py的函数,就会有内存泄漏
yuanyingtanxi 2009-03-18
  • 打赏
  • 举报
回复
to:killbug2004
我试了下,还是老样子,这个结果并不意外
毕竟即使是用boost,归跟结底还是调用Py_Initialize()和Py_Finalize(),现在我的情况是在DLL里用这两个函数就会导致内存泄漏
fibbery 2009-03-17
  • 打赏
  • 举报
回复
1、你将Execute函数注释掉,按照正常的使用去执行你的程序,看看还有没有内存泄露;
2、你将Python相关的代码都注释掉,然后,按照正常的使用去执行你的程序,看看有没有内存泄露。

通过这两个步骤,应该可以判断出内存泄露所在的位置。
yuanyingtanxi 2009-03-17
  • 打赏
  • 举报
回复
To:fibbery
析构的确被调用了,其实Py_Initialize和Py_Finalize就是放在那个Execute内部也同样会造成内存泄露

fibbery 2009-03-17
  • 打赏
  • 举报
回复
如果的的确确是内存泄露了,那么很可能是你在C/C++中使用的过程中造成的,比如,资源申请了,但是却没有释放。看到你在析构函数中有py_final的调用,我不太清楚具体资源释放需要多少个步骤,但是,从另一个角度来说,析构函数是否被调用了呢?从资源的分配和释放的对称性,楼主需要做一下全面的调试、测试。
yuanyingtanxi 2009-03-17
  • 打赏
  • 举报
回复
源码在这里
http://bbs.pythonid.com/viewthread.php?tid=2835
yuanyingtanxi 2009-03-17
  • 打赏
  • 举报
回复
to:killbug2004
如果您有这种封好的Python解释引擎邮给我一份也行,呵呵。
yuanyingtanxi@163.com
yuanyingtanxi 2009-03-17
  • 打赏
  • 举报
回复
实际上根本没什么代码,就是建了一个DLL工程,把Py_Initialize() 和Py_Finalize()放到DLL中。
EXE就是一个对话框,
// TestDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "TestDlg.h"
#include "..\ScriptEngine\PythonEngine.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialog
…………
void CTestDlg::OnBnClickedOk()
{
// TODO: Add your control notification handler code here

CPythonEngine pye;
pye.Execute("a");
OnOK();
}

killbug2004 2009-03-17
  • 打赏
  • 举报
回复
这个看不出来,内存泄露很头疼,代码传到临时网站上吧,调试看看
加载更多回复(7)

37,719

社区成员

发帖
与我相关
我的任务
社区描述
JavaScript,VBScript,AngleScript,ActionScript,Shell,Perl,Ruby,Lua,Tcl,Scala,MaxScript 等脚本语言交流。
社区管理员
  • 脚本语言(Perl/Python)社区
  • IT.BOB
加入社区
  • 近7日
  • 近30日
  • 至今

试试用AI创作助手写篇文章吧