Python Forum
Embedded Python Memory Leaks - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: Embedded Python Memory Leaks (/thread-38205.html)



Embedded Python Memory Leaks - Alexei - Sep-15-2022

Hi dear Python team,

I am a building a c/c++ application for general purpose and I would like to have in the application the possibility of running “Python” scripting code. Python has proved to be a good programming language to deal with heavy Math as in AI.

Now when I embed Python in my application things go perfect, except for memory leaks!
As a sample, by just issuing the following code leaves memory leaks of around (2Mb):

#define PY_SSIZE_T_CLEAN
#define Py_LIMITED_API 0x03000000
#include <Python.h>
#pragma comment (lib,"python3.lib")

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
{
    Py_InitializeEx(0); //For Embeded Python
    Py_FinalizeEx();
    ..More code..
    return 0;
}
Is there something I must do to cause Python to release all resources allocated

thanks


RE: Embedded Python Memory Leaks - Alexei - Sep-16-2022

Thanks for your replay Larz60, sorry I am new to this forum and I am learning how to do stuff:

The code I use is as simple as I just wrote "..mode code.." at this point is empty, since I am testing python engine before I add it to the project where I plan to use it. As you can see even the python dll gets unloaded when I finished with Python since I do late binding to python dlls due to the fact that the application might not use python for some applications while might use it for others and I don't want the user having to install python if it does not plan to use python scripting. I would like to know what does Py_InitializeEx(0); do that .Py_FinalizeEx(); cannot undo regarding computer resource utilization.

I am working with VS2019 generation a windows application 64 bits.

Thanks a log!!!


VS2019 log fragment:

Output:
'_COMCLASSES.exe' (Win32): Loaded 'C:\Python\Python311\python3.dll'. '_COMCLASSES.exe' (Win32): Loaded 'C:\Python\Python311\python311.dll'. '_COMCLASSES.exe' (Win32): Loaded 'C:\Windows\System32\bcrypt.dll'. '_COMCLASSES.exe' (Win32): Loaded 'C:\Windows\System32\version.dll'. '_COMCLASSES.exe' (Win32): Loaded 'C:\Windows\System32\vcruntime140.dll'. 0x1383630A630 -> Python Object created!... '_COMCLASSES.exe' (Win32): Unloaded 'C:\Windows\System32\version.dll' '_COMCLASSES.exe' (Win32): Unloaded 'C:\Windows\System32\vcruntime140.dll' '_COMCLASSES.exe' (Win32): Unloaded 'C:\Python\Python311\python311.dll' '_COMCLASSES.exe' (Win32): Unloaded 'C:\Python\Python311\python3.dll' 0x1383630A630 -> Python Object Destroyed!...
The object constructor runs this function and print the message "0x1383630A630 -> Python Object created!...":
# /////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT PythonObject_Init(LPPYTHONOBJECTDATA pObjectData,LPEXCEPINFO pei)
{
	HRESULT hr = S_OK;
		
	//first time Pythoon is called

	if (!hPythonDll)
	{
		if ((hr = PythonObject_BindFunctions(pObjectData, pei)) != S_OK) return hr;
	}
	if (hPythonDll && !pObjectData->bEngineInitialized)
	{
		callPython.Py_InitializeEx(0); //For Embeded Python 
		if (callPython.Py_IsInitialized())
		{
			pObjectData->bEngineInitialized = TRUE;
			callPython.PyGC_Enable();
			dwPyObjCounter++;
		}
		else hr = PythonObject_RiseException(pObjectData, pei);
	}
	
	return hr;
}

# /////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT PythonObject_BindFunctions(LPPYTHONOBJECTDATA pObjectData, LPEXCEPINFO pei)
{
	HRESULT hr = S_OK;
	
	if (pwcPyLibPathName)
	{
		hPythonDll = LoadLibrary(pwcPyLibPathName);
	
		if (hPythonDll)
		{
			char* pchar = "Py_InitializeEx";
			//Bind Functions I use
			callPython.Py_InitializeEx			= (f_Py_InitializeEx) GetProcAddress(hPythonDll, pchar);
			if (!callPython.Py_InitializeEx)				goto PythonBindError;

			pchar = "Py_IsInitialized";
			callPython.Py_IsInitialized			= (f_Py_IsInitialized)GetProcAddress(hPythonDll, pchar);
			if (!callPython.Py_IsInitialized)				goto PythonBindError;

			pchar = "Py_FinalizeEx";
			callPython.Py_FinalizeEx				= (f_Py_FinalizeEx)   GetProcAddress(hPythonDll, pchar);
			if (!callPython.Py_FinalizeEx)				goto PythonBindError;

			
			goto PyBindOk;
		PythonBindError:
			{
				wchar_t *pwcFunction = WStrFromChar(pchar);
				wchar_t* pwcDummy = NULL;
				pwcDummy = WStrConcatenate(pwcFunction, ALEXPYTHONOBJECT_ERROR_UNSSUPORTEDVERSION_STR);
				if (pwcDummy)
				{
					CreateErrorInfo2(pei, SysAllocString(pwcDummy), NULL, NULL, 0, (ALEXPYTHONOBJECT_ERROR_UNSSUPORTEDVERSION), HRESULT_CODE(ALEXPYTHONOBJECT_ERROR_UNSSUPORTEDVERSION));
				}else CreateErrorInfo2(pei, SysAllocString(ALEXPYTHONOBJECT_ERROR_UNSSUPORTEDVERSION_STR), NULL, NULL, 0, (ALEXPYTHONOBJECT_ERROR_UNSSUPORTEDVERSION), HRESULT_CODE(ALEXPYTHONOBJECT_ERROR_UNSSUPORTEDVERSION));
				return DISP_E_EXCEPTION;
			}
PyBindOk:
			hr = hr;
		}
		else
		{
			hr = GetLastError();
		}
	}
	else hr = E_INVALIDARG;
	
	return hr;
}
while the object destructor calls the following function and print the message "0x1383630A630 -> Python Object Destroyed!...":
VOID PythonObject_CleanUp(LPPYTHONOBJECTDATA pObjectData)
{
	HRESULT hr = S_OK;
	# //==============TESTING this code!!!================
	if (pObjectData->bEngineInitialized)
	{
	
		if (pObjectData->pPyMainModule)
		{
			callPython.Py_DecRef(pObjectData->pPyMainModule);
			pObjectData->pPyMainModule = NULL;
		}
		
		callPython.PyGC_Collect();
		dwPyObjCounter--;

		if (dwPyObjCounter == 0)
		{
			
			callPython.Py_FinalizeEx();
			pObjectData->bEngineInitialized = FALSE;
			if (FreeLibrary(hPythonDll))
			{
				if (pwcPyLibPathName) CoTaskMemFree(pwcPyLibPathName);
				pwcPyLibPathName = NULL;
				hPythonDll = NULL;
			}
		
		}
# //==============TESTING this code!!!================		
	}
}