iqrf 3 Posted March 5 Hi, i have this code TColumn = class(TPersistent) private FHeaderName: String; FVisible: Boolean; FWidth: Integer; FPosition: Integer; procedure SetHeaderName(const Value: String); procedure SetVisible(const Value: Boolean); procedure SetWidth(const Value: Integer); procedure SetPosition(const Value: Integer); public property HeaderName: String read FHeaderName write SetHeaderName; property Visible: Boolean read FVisible write SetVisible; property Width: Integer read FWidth write SetWidth; property Position: Integer read FPosition write SetPosition; end; TColumnWrapper = class(TPyClassWrapper<TColumn>) constructor CreateWith(APythonType: TPythonType; args, kwds: PPyObject); override; end; TTerminalLogSettings = class(TPersistent) private fColumn: TDictionary<String,TColumn>; function GetAutoScroll: Boolean; function GetSeparatorH: Boolean; function GetSeparatorV: Boolean; function GetViewData: Boolean; procedure SetAutoScroll(const Value: Boolean); procedure SetSeparatorH(const Value: Boolean); procedure SetSeparatorV(const Value: Boolean); procedure SetViewData(const Value: Boolean); public constructor Create; destructor Destroy; override; property AutoScroll: Boolean read GetAutoScroll write SetAutoScroll; property SeparatorH: Boolean read GetSeparatorH write SetSeparatorH; property SeparatorV: Boolean read GetSeparatorV write SetSeparatorV; property ViewData: Boolean read GetViewData write SetViewData; property Column: TDictionary<String, TColumn> read fColumn write fColumn; end; ... FPythonModule_TerminalLog := TPythonModule.Create(nil); FPythonModule_TerminalLog.Name := 'FPythonModule_TerminalLog'; FPythonModule_TerminalLog.Engine := FEngine; FPythonModule_TerminalLog.ModuleName := 'terminal_log'; FPythonModule_TerminalLog.OnInitialization := OnInitialization_TerminalLog; FPythonModule_TerminalLog.OnAfterInitialization := OnAfterInitialization_TerminalLog; ... FPythonVersion.AssignTo(FEngine); FEngine.LoadDll; ... terminalLogSettings := TTerminalLogSettings.Create; pTerminalLogSettings := FPythonWrapper.Wrap(terminalLogSettings, soOwned); FPythonModule_TerminalLog.SetVar( 'settings', pTerminalLogSettings); FEngine.Py_DecRef(pTerminalLogSettings); FPythonWrapper.RegisterDelphiWrapper(TColumnWrapper).Initialize; FPythonWrapper.RegisterDelphiWrapper(TPyClassWrapper<TDictionary<string, TColumn>>).Initialize; ... if used in this way in the script, then after the script finishes I correctly call the TTerminalLogSettings destructor and free the memory ... iqrfide.terminal_log.settings.autoScroll = True ... settings_object = iqrfide.terminal_log.settings setattr(settings_object, 'autoScroll', True) ... If the script is interrupted using exit(), the destructor is not called and the memory is not freed. Any explanation? ... iqrfide.terminal_log.settings.autoScroll = True ... settings_object = iqrfide.terminal_log.settings setattr(settings_object, 'autoScroll', True) exit() ... Putting settings_object = None before exit solves the problem. Share this post Link to post
pyscripter 689 Posted March 8 The exit() function raises a SystemExit exception and if it is not handled it shuts down python. Don't use it in P4D scripts. Share this post Link to post
iqrf 3 Posted March 12 Hi, not using exit() is not the solution for me. Users use exit() when debugging a script. If to ProcessSystemExit; i add Py_DecRef(errtraceback); so the memory leak problem will disappear. The destructor TTerminalLogSettings will already be called. I have no idea, but how is that possible. procedure TPythonEngine.CheckError(ACatchStopEx : Boolean = False); procedure ProcessSystemExit; var errtype, errvalue, errtraceback: PPyObject; SErrValue: string; begin PyErr_Fetch(errtype, errvalue, errtraceback); Traceback.Refresh(errtraceback); SErrValue := PyObjectAsString(errvalue); Py_DecRef(errtraceback); // workaround PyErr_Clear; raise EPySystemExit.CreateResFmt(@SPyExcSystemError, [SErrValue]); end; 1 Share this post Link to post
pyscripter 689 Posted March 13 (edited) @iqrfYou are absolutely right, PyErr_Fetch returns new references and clears the error. The code in ProcessSystemExit has now been fixed. Thanks! Edited March 13 by pyscripter Share this post Link to post