Конференция "Прочее" » Как жить дальше?
 
  • Dimka Maslov © (23.03.16 20:53) [0]
    В стародавние времена для поиска утечек памяти пользовался я FastMMом. Всё было хорошо. Но теперь, в нынешнюю годину суровых испытаний, с появлением у меня Delphi XE8 я заметил, что FastMM больше не нужен, а достаточно лишь прямо в программе указать ReportMemoryLeaksOnShutdown := True. Вроде всё хорошо, но что-то не хорошо. А именно, раньше я мог сконфигурировать всё так, чтобы при выходе из программы ещё и файлик содавался, в котором указывалось, где утёкший блок был выделен. Теперь же можно только имя класса узнать, который утёк. Или всё таки можно как-нибудь изловчиться?
  • Rouse_ © (23.03.16 21:02) [1]
    FastMM (если не считать что он уже внедрен в Delphi) нормально работает и ввиде старого варианта - с использованием внешней библиотеки, которая как раз и отвечает за создание данного лога.
  • Dimka Maslov © (23.03.16 22:03) [2]
    Т.е. всё сделать как по старому и всё заработает? А если у меня 64-бита приложение? (А оно у меня реально 64 бита).
  • DVM © (23.03.16 22:54) [3]

    >
    > Dimka Maslov ©   (23.03.16 20:53) 

    В Delphi насколько я знаю встроен урезанный FastMM4. Никто не запрещает подключить и обычный.
  • Rouse_ © (23.03.16 23:47) [4]
    за 64 бита не подскажу - в 32 битах работает норм.
  • Дмитрий Белькевич © (24.03.16 00:35) [5]
    64 норм тоже. и да, в делфе вроде урезанный. я подключаю.
  • Dimka Maslov © (24.03.16 08:38) [6]
    Понятно, спасибо.

    Только вот ещё такой вопрос. Почему когда я внутри тела потока (в перекрытом методе Execute) делаю Free - оно ругается на невысвобожденную память из-под класса потока (хотя деструктор срабатывает и все поля объекты и строки высвобождены), а вот когда я указываю FreeOnTerminate := True и Terminate, то не ругается? Это очередной баг?
  • Владислав © (24.03.16 10:31) [7]
    > Dimka Maslov ©   (24.03.16 08:38) [6]

    Почему когда я внутри тела потока (в перекрытом методе Execute) делаю Free

    Кому Free, экземпляру класса исполняемого потока???
  • Dimka Maslov © (24.03.16 10:45) [8]

    > Кому Free, экземпляру класса исполняемого потока???


    Кому же ещё?
  • Юрий Зотов © (24.03.16 11:03) [9]
    То есть, создавался объект в одном потоке, а уничтожается в другом?
  • Dimka Maslov © (24.03.16 11:04) [10]

    > То есть, создавался объект в одном потоке, а уничтожается
    > в другом?


    Что в этом плохого?
  • Владислав © (24.03.16 12:16) [11]
    > Dimka Maslov ©   (24.03.16 10:45) [8]

    Кому же ещё?

    Это потоковая функция:

    function ThreadProc(Thread: TThread): Integer;
    ...
    begin
    ...
     try
       if not Thread.Terminated then
       try
         Thread.Execute; <========= Вот тут Вы грохаете экземпляр
       except
         Thread.FFatalException := AcquireExceptionObject; <======= Далее по тексту идут обращения к грохнутому экземпляру
       end;
     finally
       FreeThread := Thread.FFreeOnTerminate;
       Result := Thread.FReturnValue;
       Thread.DoTerminate;
       Thread.FFinished := True;
       SignalSyncEvent;
       if FreeThread then Thread.Free; <=========== А тут экземпляр может еще раз грохнуться
    ...
    end;

  • Dimka Maslov © (24.03.16 12:39) [12]

    > Вот тут Вы грохаете экземпляр


    В том и вопрос, что он вообще не грохается.
  • Владислав © (24.03.16 13:45) [13]
    Грохается:

    "... (хотя деструктор срабатывает и все поля объекты и строки высвобождены) ..."

    И так делать нельзя (освобождать экземпляр класса TThread в методе Execute)!

    "... а вот когда я указываю FreeOnTerminate := True и Terminate... "

    Вот так, как выше написали, так и поступайте, раз Вам экземпляр после запуска потока не нужен.
  • Dimka Maslov © (24.03.16 14:10) [14]
    В общем, CreateThread - Наше всё!
  • NoUser © (24.03.16 14:27) [15]
    > Это очередной баг?
    Да , TThread это зло - BeginThread наше всё  ))
    Free -> WaitForSingleObject(FHandle, INFINITE); // !

  • Владислав © (24.03.16 14:49) [16]
    > Dimka Maslov ©   (24.03.16 14:10) [14]

    Да почему же. Почитать немного на эту тему.

    Ну и только не CreateThread, а BeginThread.
  • Dimka Maslov © (24.03.16 20:15) [17]
  • Nouser © (24.03.16 21:00) [18]
    Даж сишники стремаются: _beginthread/ex
    А так можно такую штучку замутить
    TWork.Add(BeginThread(nil, 0, @TWork.Run, TWork.Create, 0, PCardinal(0)^)); // ))
  • Владислав © (24.03.16 22:23) [19]
    >Dimka Maslov ©   (24.03.16 20:15) [17]

    А может все же почитать? Или самому по граблям интереснее? :)
  • Dimka Maslov © (24.03.16 22:59) [20]
    Так я и почитал. Всё ясно и понятно написано. В отличие от сайа некоей конторы.
  • DVM © (24.03.16 23:17) [21]

    > Dimka Maslov ©   (24.03.16 20:15) [17]

    1) Не кроссплатформенно
    2) Не выставляет флаг IsMultithreaded автоматом.
  • Kerk © (24.03.16 23:57) [22]
    А чем можно смотреть использование памяти в рантайм? В смысле - сделать снимок и посмотреть кто, сколько и для чего памяти выделил. Бывает такое бесплатное?
  • Kerk © (24.03.16 23:57) [22]
    А чем можно смотреть использование памяти в рантайм? В смысле - сделать снимок и посмотреть кто, сколько и для чего памяти выделил. Бывает такое бесплатное?
  • Kerk © (24.03.16 23:57) [22]
    А чем можно смотреть использование памяти в рантайм? В смысле - сделать снимок и посмотреть кто, сколько и для чего памяти выделил. Бывает такое бесплатное?
  • Германн © (25.03.16 01:55) [23]

    > Dimka Maslov ©   (24.03.16 12:39) [12]
    >
    >
    > > Вот тут Вы грохаете экземпляр
    >
    >
    > В том и вопрос, что он вообще не грохается.

    на каких основаниях сделан такой вывод.
  • Германн © (25.03.16 01:55) [23]

    > Dimka Maslov ©   (24.03.16 12:39) [12]
    >
    >
    > > Вот тут Вы грохаете экземпляр
    >
    >
    > В том и вопрос, что он вообще не грохается.

    на каких основаниях сделан такой вывод.
  • Германн © (25.03.16 01:55) [23]

    > Dimka Maslov ©   (24.03.16 12:39) [12]
    >
    >
    > > Вот тут Вы грохаете экземпляр
    >
    >
    > В том и вопрос, что он вообще не грохается.

    на каких основаниях сделан такой вывод.
  • Eraser © (25.03.16 05:38) [24]

    > Dimka Maslov ©   (24.03.16 08:38) [6]

    TThread - один из самых удобных классов в Делфи. Разве что потоковые нововведения в самых новых версиях делфи могут соперничать (parallel lib).
    Прежде чем использовать TThread, нужно проникнуться его идеологией, хотя бы поверхностно, а не кидаться удалять объект изнутри самого себя.
    Одна из сильнейших сторон TThread - событие OnTerminate, выполняющиеся всегда в контексте главного потока.

    Вообще современный TThread чего только не умеет.


    procedure TForm1.Button1Click(Sender: TObject);
    var
     I: Integer;
    begin
     I := 1;
     TThread.CreateAnonymousThread(
       procedure
       begin
         Inc(I);
         TThread.Queue(nil,
           procedure
           begin
             ShowMessage(I.ToString);
           end
         );
       end
     ).Start;
    end;
  • Eraser © (25.03.16 05:38) [24]

    > Dimka Maslov ©   (24.03.16 08:38) [6]

    TThread - один из самых удобных классов в Делфи. Разве что потоковые нововведения в самых новых версиях делфи могут соперничать (parallel lib).
    Прежде чем использовать TThread, нужно проникнуться его идеологией, хотя бы поверхностно, а не кидаться удалять объект изнутри самого себя.
    Одна из сильнейших сторон TThread - событие OnTerminate, выполняющиеся всегда в контексте главного потока.

    Вообще современный TThread чего только не умеет.


    procedure TForm1.Button1Click(Sender: TObject);
    var
     I: Integer;
    begin
     I := 1;
     TThread.CreateAnonymousThread(
       procedure
       begin
         Inc(I);
         TThread.Queue(nil,
           procedure
           begin
             ShowMessage(I.ToString);
           end
         );
       end
     ).Start;
    end;
  • Eraser © (25.03.16 05:38) [24]

    > Dimka Maslov ©   (24.03.16 08:38) [6]

    TThread - один из самых удобных классов в Делфи. Разве что потоковые нововведения в самых новых версиях делфи могут соперничать (parallel lib).
    Прежде чем использовать TThread, нужно проникнуться его идеологией, хотя бы поверхностно, а не кидаться удалять объект изнутри самого себя.
    Одна из сильнейших сторон TThread - событие OnTerminate, выполняющиеся всегда в контексте главного потока.

    Вообще современный TThread чего только не умеет.


    procedure TForm1.Button1Click(Sender: TObject);
    var
     I: Integer;
    begin
     I := 1;
     TThread.CreateAnonymousThread(
       procedure
       begin
         Inc(I);
         TThread.Queue(nil,
           procedure
           begin
             ShowMessage(I.ToString);
           end
         );
       end
     ).Start;
    end;
  • Dimka Maslov © (25.03.16 09:38) [25]

    > 1) Не кроссплатформенно


    И пёс с им.


    > на каких основаниях сделан такой вывод.


    На основании анализа утечек памяти.


    >  событие OnTerminate


    Легко заменяется на SendMessage(Application.MainFormHandle, .....), которое тоже выполнится в контексте главного потока.
  • Dimka Maslov © (25.03.16 09:38) [25]

    > 1) Не кроссплатформенно


    И пёс с им.


    > на каких основаниях сделан такой вывод.


    На основании анализа утечек памяти.


    >  событие OnTerminate


    Легко заменяется на SendMessage(Application.MainFormHandle, .....), которое тоже выполнится в контексте главного потока.
  • Dimka Maslov © (25.03.16 09:38) [25]

    > 1) Не кроссплатформенно


    И пёс с им.


    > на каких основаниях сделан такой вывод.


    На основании анализа утечек памяти.


    >  событие OnTerminate


    Легко заменяется на SendMessage(Application.MainFormHandle, .....), которое тоже выполнится в контексте главного потока.
  • DVM © (25.03.16 11:41) [26]

    > Dimka Maslov ©   (25.03.16 09:38) [25]


    > Легко заменяется на SendMessage(Application.MainFormHandle,
    >  .....), которое тоже выполнится в контексте главного потока.

    При условии наличия окон в программе и цикла выборки сообщений. OnTerminate не требует окон.
  • DVM © (25.03.16 11:41) [26]

    > Dimka Maslov ©   (25.03.16 09:38) [25]


    > Легко заменяется на SendMessage(Application.MainFormHandle,
    >  .....), которое тоже выполнится в контексте главного потока.

    При условии наличия окон в программе и цикла выборки сообщений. OnTerminate не требует окон.
  • DVM © (25.03.16 11:41) [26]

    > Dimka Maslov ©   (25.03.16 09:38) [25]


    > Легко заменяется на SendMessage(Application.MainFormHandle,
    >  .....), которое тоже выполнится в контексте главного потока.

    При условии наличия окон в программе и цикла выборки сообщений. OnTerminate не требует окон.
  • NoUser © (25.03.16 14:48) [27]
    > OnTerminate не требует окон.
    А чего тогда требует?
  • NoUser © (25.03.16 14:48) [27]
    > OnTerminate не требует окон.
    А чего тогда требует?
  • NoUser © (25.03.16 14:48) [27]
    > OnTerminate не требует окон.
    А чего тогда требует?
  • DVM © (25.03.16 17:00) [28]

    > NoUser ©   (25.03.16 14:48) [27]


    > А чего тогда требует?

    OnTerminate через  Synchronize вызывается. Теперешний Synchronize уже не использует сообщений как раньше. Подробности см. реализацию Synchronize
  • DVM © (25.03.16 17:00) [28]

    > NoUser ©   (25.03.16 14:48) [27]


    > А чего тогда требует?

    OnTerminate через  Synchronize вызывается. Теперешний Synchronize уже не использует сообщений как раньше. Подробности см. реализацию Synchronize
  • DVM © (25.03.16 17:00) [28]

    > NoUser ©   (25.03.16 14:48) [27]


    > А чего тогда требует?

    OnTerminate через  Synchronize вызывается. Теперешний Synchronize уже не использует сообщений как раньше. Подробности см. реализацию Synchronize
  • NoUser © (25.03.16 17:50) [29]
    Вот мне и интересно, как сделать основной поток (без окон), чтобы этот OnTerminate там отработал?
  • NoUser © (25.03.16 17:50) [29]
    Вот мне и интересно, как сделать основной поток (без окон), чтобы этот OnTerminate там отработал?
  • NoUser © (25.03.16 17:50) [29]
    Вот мне и интересно, как сделать основной поток (без окон), чтобы этот OnTerminate там отработал?
  • DVM © (25.03.16 18:17) [30]

    > Вот мне и интересно, как сделать основной поток (без окон),
    >  чтобы этот OnTerminate там отработал?


    program Project1;

    {$APPTYPE CONSOLE}

    {$R *.res}

    uses
     System.SysUtils, System.Classes;

    type

     TMyThread = class(TThread)
     protected
       procedure Execute; override;
     end;

     TMyClass = class
     private
       FSecondThread: TMyThread;
       procedure ThreadTreminated(Sender: TObject);
     public
       constructor Create;
       destructor Destroy; override;
       procedure Run;
     end;

    var
     MyClass: TMyClass;

    { TMyClass }

    constructor TMyClass.Create;
    begin
     inherited Create;
     FSecondThread := TMyThread.Create;
     FSecondThread.FreeOnTerminate := True;
     FSecondThread.OnTerminate := ThreadTreminated;
    end;

    destructor TMyClass.Destroy;
    begin
     FSecondThread.Free;
     inherited;
    end;

    procedure TMyClass.Run;
    var
     i: integer;
    begin
     for I := 0 to 9 do
       begin
         Writeln(I);
         CheckSynchronize;
         Sleep(1000);
       end;
    end;

    procedure TMyClass.ThreadTreminated(Sender: TObject);
    begin
     Writeln('Second thread terminated');
    end;

    { TMyThread }

    procedure TMyThread.Execute;
    begin
     Writeln('Second thread start');
     Sleep(2000);
     Writeln('Second thread end');
    end;

    begin
     try
       MyClass := TMyClass.Create;
       try
         MyClass.Run;
       finally
         MyClass.Free;
       end;

     except
       on E: Exception do
         Writeln(E.ClassName, ': ', E.Message);
     end;
     Readln;
    end.

  • DVM © (25.03.16 18:17) [30]

    > Вот мне и интересно, как сделать основной поток (без окон),
    >  чтобы этот OnTerminate там отработал?


    program Project1;

    {$APPTYPE CONSOLE}

    {$R *.res}

    uses
     System.SysUtils, System.Classes;

    type

     TMyThread = class(TThread)
     protected
       procedure Execute; override;
     end;

     TMyClass = class
     private
       FSecondThread: TMyThread;
       procedure ThreadTreminated(Sender: TObject);
     public
       constructor Create;
       destructor Destroy; override;
       procedure Run;
     end;

    var
     MyClass: TMyClass;

    { TMyClass }

    constructor TMyClass.Create;
    begin
     inherited Create;
     FSecondThread := TMyThread.Create;
     FSecondThread.FreeOnTerminate := True;
     FSecondThread.OnTerminate := ThreadTreminated;
    end;

    destructor TMyClass.Destroy;
    begin
     FSecondThread.Free;
     inherited;
    end;

    procedure TMyClass.Run;
    var
     i: integer;
    begin
     for I := 0 to 9 do
       begin
         Writeln(I);
         CheckSynchronize;
         Sleep(1000);
       end;
    end;

    procedure TMyClass.ThreadTreminated(Sender: TObject);
    begin
     Writeln('Second thread terminated');
    end;

    { TMyThread }

    procedure TMyThread.Execute;
    begin
     Writeln('Second thread start');
     Sleep(2000);
     Writeln('Second thread end');
    end;

    begin
     try
       MyClass := TMyClass.Create;
       try
         MyClass.Run;
       finally
         MyClass.Free;
       end;

     except
       on E: Exception do
         Writeln(E.ClassName, ': ', E.Message);
     end;
     Readln;
    end.

  • DVM © (25.03.16 18:17) [30]

    > Вот мне и интересно, как сделать основной поток (без окон),
    >  чтобы этот OnTerminate там отработал?


    program Project1;

    {$APPTYPE CONSOLE}

    {$R *.res}

    uses
     System.SysUtils, System.Classes;

    type

     TMyThread = class(TThread)
     protected
       procedure Execute; override;
     end;

     TMyClass = class
     private
       FSecondThread: TMyThread;
       procedure ThreadTreminated(Sender: TObject);
     public
       constructor Create;
       destructor Destroy; override;
       procedure Run;
     end;

    var
     MyClass: TMyClass;

    { TMyClass }

    constructor TMyClass.Create;
    begin
     inherited Create;
     FSecondThread := TMyThread.Create;
     FSecondThread.FreeOnTerminate := True;
     FSecondThread.OnTerminate := ThreadTreminated;
    end;

    destructor TMyClass.Destroy;
    begin
     FSecondThread.Free;
     inherited;
    end;

    procedure TMyClass.Run;
    var
     i: integer;
    begin
     for I := 0 to 9 do
       begin
         Writeln(I);
         CheckSynchronize;
         Sleep(1000);
       end;
    end;

    procedure TMyClass.ThreadTreminated(Sender: TObject);
    begin
     Writeln('Second thread terminated');
    end;

    { TMyThread }

    procedure TMyThread.Execute;
    begin
     Writeln('Second thread start');
     Sleep(2000);
     Writeln('Second thread end');
    end;

    begin
     try
       MyClass := TMyClass.Create;
       try
         MyClass.Run;
       finally
         MyClass.Free;
       end;

     except
       on E: Exception do
         Writeln(E.ClassName, ': ', E.Message);
     end;
     Readln;
    end.

  • DVM © (25.03.16 18:20) [31]
    Небольшое уточнение, надо убрать FSecondThread.FreeOnTerminate := True;
  • DVM © (25.03.16 18:20) [31]
    Небольшое уточнение, надо убрать FSecondThread.FreeOnTerminate := True;
  • DVM © (25.03.16 18:20) [31]
    Небольшое уточнение, надо убрать FSecondThread.FreeOnTerminate := True;
  • NoUser © (25.03.16 19:07) [32]
    Спасибо, но как я и думал, чуда не произошло - CheckSynchronize.
    ЗЫ.
    А какая версия Dx ?
  • NoUser © (25.03.16 19:07) [32]
    Спасибо, но как я и думал, чуда не произошло - CheckSynchronize.
    ЗЫ.
    А какая версия Dx ?
  • NoUser © (25.03.16 19:07) [32]
    Спасибо, но как я и думал, чуда не произошло - CheckSynchronize.
    ЗЫ.
    А какая версия Dx ?
  • DVM © (25.03.16 21:46) [33]

    > NoUser ©   (25.03.16 19:07) [32]


    > чуда не произошло - CheckSynchronize.

    Разумеется, чуда никакого нет и не может быть. Никто, кроме самого потока не может выполнить код в его контексте. Собственно внутри CheckSynchronize и происходит выборка из очереди действия для выполнения потоком и собственно выполнение.


    > А какая версия Dx ?
    >
    >

    У меня D8. Но CheckSynchronize  существует очень давно, в 2009 уже было вроде, а может и раньше.
  • DVM © (25.03.16 21:46) [33]

    > NoUser ©   (25.03.16 19:07) [32]


    > чуда не произошло - CheckSynchronize.

    Разумеется, чуда никакого нет и не может быть. Никто, кроме самого потока не может выполнить код в его контексте. Собственно внутри CheckSynchronize и происходит выборка из очереди действия для выполнения потоком и собственно выполнение.


    > А какая версия Dx ?
    >
    >

    У меня D8. Но CheckSynchronize  существует очень давно, в 2009 уже было вроде, а может и раньше.
  • DVM © (25.03.16 21:46) [33]

    > NoUser ©   (25.03.16 19:07) [32]


    > чуда не произошло - CheckSynchronize.

    Разумеется, чуда никакого нет и не может быть. Никто, кроме самого потока не может выполнить код в его контексте. Собственно внутри CheckSynchronize и происходит выборка из очереди действия для выполнения потоком и собственно выполнение.


    > А какая версия Dx ?
    >
    >

    У меня D8. Но CheckSynchronize  существует очень давно, в 2009 уже было вроде, а может и раньше.
  • Германн © (25.03.16 23:05) [34]
    Раньше. В Д2007 точно был.
  • Германн © (25.03.16 23:05) [34]
    Раньше. В Д2007 точно был.
  • Германн © (25.03.16 23:05) [34]
    Раньше. В Д2007 точно был.
 
Конференция "Прочее" » Как жить дальше?
Есть новые Нет новых   [134434   +28][b:0.001][p:0.005]