Утечка памяти при создании потока

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Утечка памяти при создании потока

Сообщение Deimos » 19.03.2025 11:36:27

Всем доброго...

Не могу разобраться (лыжи не едут)...

Пустой примитивный поток

Пустая форма и утечка памяти...

Поток:

Код: Выделить всё
unit dirmon;

{$mode ObjFPC}{$H+}

interface

uses Classes, Windows, SysUtils;

type

  { TChangeMonitor }

  TChangeMonitor = class(TThread)
    private
    public
      constructor Create(ASuspended: boolean);
      destructor destroy; override;
    protected
      procedure Execute; override;
  end;

implementation

constructor TChangeMonitor.Create(ASuspended: boolean);
begin
  inherited Create(ASuspended);
  FreeOnTerminate:=true;
end;

destructor TChangeMonitor.destroy;
begin
  inherited destroy;
end;

procedure TChangeMonitor.Execute;
begin

end;

end.


Форма:

Код: Выделить всё
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, dirmon;

type

  { TForm1 }

  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
     tmp:TChangeMonitor;
  public

  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin
  tmp:=TChangeMonitor.Create(true);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  tmp.Terminate;
end;

end.



Heap:

E:\Code\LCommander\threadsTest\test.exe
Heap dump by heaptrc unit of E:\Code\LCommander\threadsTest\test.exe
940 memory blocks allocated : 1447336/1448112
938 memory blocks freed : 1447240/1448016
2 unfreed memory blocks : 96
True heap size : 1540096 (160 used in System startup)
True free heap : 1539392
Should be : 1539456
Call trace for block $00000000016AE690 size 24
$000000010001180F
$000000010001388E
$000000010001315F
$000000010004B990
$000000010004BC88
$0000000100034E6A Create, line 26 of dirmon.pas
$0000000100034DC7 FormCreate, line 34 of unit1.pas
$00000001000239A3 DOCREATE, line 922 of include/customform.inc
$000000010002180E AFTERCONSTRUCTION, line 77 of include/customform.inc
$00000001000299BF CREATE, line 3218 of include/customform.inc
$0000000100031C28 CREATEFORM, line 2243 of include/application.inc
$0000000100002CA0 $main, line 23 of test.lpr
$0000000100002CC6
$00000001000175C0
$0000000100002C2B
$00007FFC9487259D
Call trace for block $0000000001614AD0 size 72
$0000000100011729
$000000010000E188
$0000000100034E3A Create, line 25 of dirmon.pas
$0000000100034DC7 FormCreate, line 34 of unit1.pas
$00000001000239A3 DOCREATE, line 922 of include/customform.inc
$000000010002180E AFTERCONSTRUCTION, line 77 of include/customform.inc
$00000001000299BF CREATE, line 3218 of include/customform.inc
$0000000100031C28 CREATEFORM, line 2243 of include/application.inc
$0000000100002CA0 $main, line 23 of test.lpr
$0000000100002CC6
$00000001000175C0
$0000000100002C2B
$00007FFC9487259D
$00007FFC9614AF38
$0000000100002C2B
$00007FFC9487259D

WIN11_64 PRO
Lazarus 3.8 32/64
FPC 3.2.2
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Deimos
постоялец
 
Сообщения: 174
Зарегистрирован: 17.01.2010 00:31:30

Re: Утечка памяти при создании потока

Сообщение xchgeaxeax » 19.03.2025 11:52:57

Попробуйте так:
Код: Выделить всё
procedure TForm1.FormDestroy(Sender: TObject);
begin
  tmp.Terminate;
  FreeAndNil(tmp);
end;
xchgeaxeax
постоялец
 
Сообщения: 173
Зарегистрирован: 11.05.2023 03:51:40

Re: Утечка памяти при создании потока

Сообщение Deimos » 19.03.2025 12:03:06

xchgeaxeax

он-жеж
Код: Выделить всё
FreeOnTerminate:=true;
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Deimos
постоялец
 
Сообщения: 174
Зарегистрирован: 17.01.2010 00:31:30

Re: Утечка памяти при создании потока

Сообщение xchgeaxeax » 19.03.2025 12:56:57

Deimos писал(а):xchgeaxeax

он-жеж
Код: Выделить всё
FreeOnTerminate:=true;

Так вы тред запустите

Добавлено спустя 29 минут 1 секунду:
Я так понял вы не понимаете что именно происходит в вашем коде.
В дополнительном потоке будет работать только этот код
Код: Выделить всё
procedure TChangeMonitor.Execute;
begin

end;
Но эта процедура пустая и поэтому тред сразу помрет. Зато останется ThreadID, ThreadHandle и ExitCodeThread

А вот что происходит в основном треде вашей программы (я просто соберу процедуры подряд)
Код: Выделить всё
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
     tmp:TChangeMonitor;
  public

  end;

// Это дефолтный класс формы, который вами был дополнен приватным полем tmp (этим полем владеет класс формы и время жизни должен контролировать именно он; здесь все верно)

procedure TForm1.FormCreate(Sender: TObject);
begin // Обработчик создания объекта TForm1 заодно создает объект tmp
  tmp:=TChangeMonitor.Create(true);
end;

constructor TChangeMonitor.Create(ASuspended: boolean {true из TForm1.FormCreate});
begin // Конструктор объекта треда (он выполняется в основном треде, а не создаваемом)
  inherited Create(ASuspended); // Вызов конструктора TThread.Create(true). Т.е. поток должен быть приостановлен после создания объекта его описания
  FreeOnTerminate:=true; // Вы выключаете автоматическое уничтожение объекта описания потока после завершения (выхода из процедуры Execute, а не сразу по TThread.Terminate)
// Это хорошо. Так форма сможет контролировать время жизни переменной tmp
end;
Но вот вы не запустили поток и реального системного объекта Thread не создано, который и будет этим самым тредом исполняющим Execute

После же нажатия на крестик у формы выполняется следующее
Код: Выделить всё
procedure TForm1.FormDestroy(Sender: TObject);
begin
  tmp.Terminate; // Вы переключаете состояние потока в Terminated и не дождавшись его окончания просто уничтожаете объект его описания. Так можно делать, но осторожно
// А вот проблема как раз тут в следующем: Нету реального системного Thread т.к. у вас в TForm1.FormCreate создан замороженный поток. Поэтому его нельзя уничтожить и отсюда ошибка хэндла
  FreeAndNil(tmp); // А вот эта команда нужна т.к. вы сделали FreeOnTerminate:=true; чтобы устранить утечку памяти в объекте tmp, о которой ваше сообщение из 1 поста
// После этого будет вызвана TChangeMonitor.destroy
end;

destructor TChangeMonitor.destroy;
begin
  inherited destroy; // Которая просто вызовет TThread.Destroy;
end;
xchgeaxeax
постоялец
 
Сообщения: 173
Зарегистрирован: 11.05.2023 03:51:40

Re: Утечка памяти при создании потока

Сообщение Deimos » 19.03.2025 13:34:12

Признаю - мой косяк )
Deimos
постоялец
 
Сообщения: 174
Зарегистрирован: 17.01.2010 00:31:30


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 15

Рейтинг@Mail.ru