Rambler's Top100
"Knowledge itself is power"
F.Bacon
Поиск | Карта сайта | Помощь | О проекте | ТТХ  
 Круглый стол
  
Правила КС
>> Настройки

Фильтр вопросов
>> Новые вопросы
отслеживать по
>> Новые ответы

Избранное

Страница вопросов
Поиск по КС


Специальные проекты:
>> К л ю к в а
>> Г о л о в о л о м к и

Вопрос №

Задать вопрос
Off-topic вопросы

Помощь

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
  
 
Во Флориде и в Королевстве сейчас  21:45[Войти] | [Зарегистрироваться]
Ответ на вопрос № 67842

13-01-2009 06:31
Здравствуйте!
Вопрос по отладке приложений. Я написал Direct3D-шный screensaver.
Все работает стабильно, но иногда приложение зависает. Не могу найти закономерности.
Суть программы в показе примитивного слайд-шоу. Работает с одними и теми же файлами.
Изображения для слайд-шоу загружаются в отдельных потоках, потом синхронизируются, потом загружаются в текстуры.
Проверял process explorer-ом на предмет утечки памяти. Объем занимаемой памяти не увеличивается,
но постоянно растет page faults.
Я не очень опытный в вопросе работы с DirectX, возможно я неправильно освобождаю текстуры или что-нибудь еще…
Бывают ли утечки видео памяти? Если да, то как их проверить? Нужно ли освобождать текстуру и спрайт перед каждой загрузкой нового изображения?

Извините за изобилие вопросов, просто теряюсь в догадках. Основной вопрос: как найти ошибку?
Заранее благодарен,
Дмитрий.

[+] Добавить в избранные вопросы

Отслеживать ответы на этот вопрос по RSS

Ответы:


Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице.
Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.

21-01-2009 15:43
Да да да!
Так я и думал :)
Спасибо еще раз.
Вопрос решен.

21-01-2009 10:00
Я редко пользуюсь дельфияскими графическими объектами, потому могу и ошибаться. Насколько помню, в конце петли выборки сообщений главного потока производится освобождение HDC всех незалоченных Canvas. Так как Вы рисуете в доп. потоке, то может случиться так, что HDC канвы Вашего битмапа будет освобожден как раз в момент рисования. Чтобы этого избежать, канву следует залочить. Только надо, видимо, вызовы Canvas.Lock и Unlock перенести в доп.поток.


    begin
      NewBitMap:= TBitmap(Msg.WParam);
      NewBitMap.Canvas.Lock;
      try

      FNameToLoad:= PChar(Msg.LParam);
      StrDispose(PChar(Msg.LParam));
    // тут делаем страшные операции с  jpeg, NewBitMap, и Stream
      finally
        NewBitMap.Canvas.Unlock;
      end;

      PostMessage(Form1.Handle, WM_THREAD_COMPLETE, 0, 0);
    end


а в других местах убрать. Но точно я не помню, попробуйте.

Надеюсь, однако, что если я неправ, то более знающие люди меня поправят.

21-01-2009 09:30
Есть еще один маленький вопрос по запуску потока на обработку
У меня все прекрасно работает без

  FBitmap.Canvas.Lock; 

здесь:

var
  P: PChar;
begin
  P:= StrAlloc(PChar(ListBox1.Items[Form1.ListBox1.ItemIndex]));
  FBitmap.Canvas.Lock; //
  PostThreadMessage(FMyThread.ThreadID, UM_NEWBITMAP, integer(FBitmap), integer(P));
// FBitmap здесь передавать не обязательно, его можно сразу указать при создании потока
end;



Дело в том, что в конце страшных операций с  jpeg, NewBitMap, и Stream я получаю результат, который нужно передать в основной поток,
используя FBitmap.
Насколько я понимаю, 

PostThreadMessage(FMyThread.ThreadID, UM_NEWBITMAP, integer(FBitmap), integer(P));


передает рабочему потоку ссылку на FBitmap? А рабочий поток, пытаясь нарисовать на канве FBitmap-а вызывает ошибку.
Зачем тогда лочить канву? Или ее нужно разлочить перед передачей результатов работы? Тогда теряться смысл блокировки, так как в любой момент процессорное время может быть переключено на основной поток.
Если это важно, то я запускаю только один экземпляр рабочего потока.

P.S. Спасибо огромное за код, с потоком, который постоянно работает. Операции стали производиться четче и быстрее. ;)

20-01-2009 20:58
Здесь, я так понимаю нужно добавить StrPLCopy(

Или заменить StrAlloc на StrNew

Есть ли ограничения данного метода для windows 2000?

Нет.
 NS

20-01-2009 18:38
Пока работает на XP :) , но не на 2000.
Есть ли ограничения данного метода для windows 2000?
Мне нужно получить результат для 2000/XP/Vista.
Спасибо.

20-01-2009 11:49
Пока что читаю "Основы работы с Win API в VCL-приложениях"
http://www.delphikingdom.com/asp/viewitem.asp?catalogid=169&mode=print
Всем новичкам,  столкнувшимся с данной проблемой советую.

Буду благодарен за любую помощь в данном вопросе, так как проблема срочная, а мое незнание WinAPI сильно тормозит процесс.

20-01-2009 11:46

var
...
  Msg: TMsg;
begin
// Вот этот оператор привел меня в замешательсво
  PeekMessage(..., PM_NOREMOVE);

// Здесь создаем t_bitmap, JPeg, стрим и все что надо
  try
  while GetMessage(Msg. 0, 0, 0) do

// Я втавил
    if Msg.message = WM_NEWBITMAP then
//Вместо
//    if Msg.msg = VM_NEWBITMAP then
//Это правильно?

    begin
      NewBitMap:= TBitmap(Msg.WParam);
      FNameToLoad:= PChar(Msg.LParam);
      StrDispose(PChar(Msg.LParam));
    // тут делаем страшные операции с  jpeg, NewBitMap, и Stream
      PostMessage(Form1.Handle, WM_THREAD_COMPLETE, 0, 0);
    end;
  finally
// Здесь все созданное уничтожаем
// NewBitMap не трогать!!!
  end;


20-01-2009 11:42
Спасибо!
Я не силен в WinAPI, но общие представления имею.
Целый день провел в попытках сделать приведенный пример рабочим - пока тчетно :(

Есть вопросы:

var
  P: PChar;
begin
  P:= StrAlloc(PChar(ListBox1.Items[Form1.ListBox1.ItemIndex]));
//Здесь, я так понимаю нужно добавить
  StrPLCopy(P, ListBox1.Items[Form1.ListBox1.ItemIndex],
              Length(ListBox1.Items[Form1.ListBox1.ItemIndex]));

  FBitmap.Canvas.Lock;
  PostThreadMessage(FMyThread.ThreadID, UM_NEWBITMAP, integer(FBitmap), integer(P));
// FBitmap здесь передавать не обязательно, его можно сразу указать при создании потока
// Я не очень понял как именно мы передаем FBitmap. Если можно краткий комент - это было бы здорово.
end;


19-01-2009 23:38
Судя по коду, понятие "синхронизация потоков" Вам не знакомо:)
Не уверен, что правильно понял идею, но если понял то:

Не вижу смысла создавать каждый раз новый поток, как, впрочем, и остальные ресурсы.
Функция потока может выглядеть примерно так


var
...
  Msg: TMsg;
begin
  PeekMessage(..., PM_NOREMOVE);
// Здесь создаем t_bitmap, JPeg, стрим и все что надо
  try
  while GetMessage(Msg. 0, 0, 0) do
    if Msg.Msg = UM_NEWBITMAP then
    begin
      NewBitMap:= TBitmap(Msg.WParam);
      FNameToLoad:= PChar(Msg.LParam);
      StrDispose(PChar(Msg.LParam));
    // тут делаем страшные операции с  jpeg, NewBitMap, и Stream
      PostMessage(Form1.Handle, WM_THREAD_COMPLETE, 0, 0);
    end;
  finally
// Здесь все созданное уничтожаем
// NewBitMap не трогать!!!
  end;



В приватную секцию формы добавить поля FMyThread: TMyThread и FBitmap: TBitmap, создание и инициализацию обоих разместить в OnCreate формы. Запуск потока на обработку выполнять примерно так:


var
  P: PChar;
begin
  P:= StrAlloc(PChar(ListBox1.Items[Form1.ListBox1.ItemIndex]));
  FBitmap.Canvas.Lock; //
  PostThreadMessage(FMyThread.ThreadID, UM_NEWBITMAP, integer(FBitmap), integer(P));
// FBitmap здесь передавать не обязательно, его можно сразу указать при создании потока
end;


А обработчик WM_THREAD_COMPLETE в форме выплнить так:


begin
  NextTexture.Assign(FBitMap); // если это вообще нужно
  FBitmap.Canvas.Unlock;
  need_to_reload_textures := True;
end;


На OnDestroy формы уничтожаем сначала FMyThread, потом FBitmap


begin
  PostThreadMessage(FMyThread.ThreadID, WM_QUIT, 0, 0);
  FMyThread.Free;
  FBitmap.Free;
...
end;


Как-то так, видимо.

19-01-2009 20:50
Действительно проблемы с потоками.


  type
    TMyThread = class(TThread)
  Private
      FResult:      Boolean;
      FFNameToLoad: string;
      FScreenWidth:  Integer;
      FScreenHeight: Integer;
      FNewBitMap:TBitmap;
  protected
    procedure Execute; override;
  public
  //  NewBitMap: TBitMap;
    property NewBitMap: TBitMap read FNewBitMap write FNewBitMap ;
    property FNameToLoad: string read FFNameToLoad write FFNameToLoad;
    property ScreenWidth: Integer read FScreenWidth  write FScreenWidth;
    property ScreenHeight:Integer read FScreenHeight write FScreenHeight;
    property Result: Boolean read FResult write FResult;
  end;




procedure TMyThread.Execute;
var
  j, new_h, new_w, new_x, new_y: integer;
  s: ansistring;
  f_ext:string;
  jpeg: TJpegImage;
  Stream: TMemoryStream;
  t_bitmap: TBitmap;
begin
  Result:=true;
  t_bitmap := TBitmap.Create;
  NewBitMap:=TBitmap.Create;
  with NewBitMap do
  begin
    PixelFormat:=pf24bit;
    Width  := ScreenWidth;
    Height := ScreenHeight;
  end;
  jpeg := TJPEGImage.Create;
  jpeg.CompressionQuality := 100;
  Stream := TMemoryStream.Create;
  try
    try
    // тут делаем страшные операции с  jpeg, NewBitMap, и Stream пока не выкладываю,
          // думаю, они не играют ключевую роль

    except
      on E: Exception do
      begin
        Result:= false;
        LogErrorThread(E.Message,'TMyThread.Execute');
      end
    end;
    if not Terminated then
    begin

        //Временное решение. Пока-что единственный способ, который дал мне результат. :(
            if Assigned(Form1.NextTexture) then
            Form1.NextTexture.Assign(NewBitMap);

      PostMessage(Form1.Handle, WM_THREAD_COMPLETE, 0, 0);
    end;
  finally
    if t_bitmap<>nil then
      t_bitmap.Free;
    if jpeg<>nil then
      jpeg.Free;
    if Stream<>nil then
      Stream.Free;
    if newbitmap<>nil then
      newbitmap.Free;
  end;
end;



Вот эта процедура запускается, когда рабочий поток посылает сообщение основному



procedure TForm1.HandleThreadCompletion(var Message: TMessage);
var St:TMemoryStream;
begin
  if Assigned(MyThread1) then
  begin
    MyThread1.WaitFor;
    try
не работает :(
//    form1.NextTexture.Assign(MyThread1.NewBitMap);

работает 
//  MyThread1.NewBitMap.SaveToFile('c:\x.bmp');
//  form1.NextTexture.LoadFromFile('c:\x.bmp');

      need_to_reload_textures := True;
    finally
      MyThread1.Free;
      MyThread1 := nil;
    end;
  end;
end;



Запуск потока:


  if not Assigned(MyThread1)  then
    begin
        MyThread1:=TMyThread.Create(True);
        MyThread1.FreeOnTerminate:=false;
        try
          with MyThread1 do
          begin
            // NewBitMap:=nil;
            ScreenWidth:=Screen.Width;
            ScreenHeight:=Screen.Height;
            FNameToLoad := Form1.ListBox1.Items[Form1.ListBox1.ItemIndex];
            Resume;
          end;
        except
          on E: Exception do
          begin
              LogError(E.Message,'TForm1.Pict_Change');
              MyThread1.Free;
              MyThread1:=nil;
              exit;
          end;
        end;
    end;



и вот теперь есть проблема, которую не могу побороть: Я хотел считывать обработанный bitmap в  TForm1.HandleThreadCompletion.
Но, при данном коде рабочего потока - MyThread.newbitmap.free будет выполнена, и не факт, что основной поток успеет обработать сообщение. Освободить TMyThread.newbitmap в  TForm1.HandleThreadCompletion не удается.
Если ее не освобождать - происходит утечка.
Вообще "извлечь" данные TMyThread.newbitmap по окончанию TMyThread.Execute удается лишь извращенными способами вроде записи на жесткий диск или в Tmemorystream...

Подскажите пожалуйста, как поправить код, чтобы корректно присваивать Form1.NextTexture изображение полученное в MyThread1.NewBitmap...

18-01-2009 18:47
Спасибо!
Буду искать дальше.

17-01-2009 22:25
поиск утечек, которые корректно освобождаются по завершению программы

Если память была выделена в процессе работ+ы, а при завершении программы корректно освобождена, то это строго говоря не утечка. Для любого инструмента контроля все будет выглядеть нормально. Другое дело, что с точки зрения логики это может быть неправильным, но это можете определить только Вы сами.

Проблема таки в организации многопоточной работы

Скорее всего у Вас происходит взаимоблокировка дыух или нескольких потоков. Типа поток 1 ждет, когда поток 2 выполнит действие A, а в это время поток 2 ждет, когда поток 1 выполнит действие B. Попробуйте определить место, на котором зависают Ваши потоки.

17-01-2009 10:03
Спасибо!
Кажется, я близок к решению.
Проблема таки в организации многопоточной работы.  :)
А возможно ли каким-то образом автоматизировать поиск утечек, которые корректно освобождаются по завершению программы?

17-01-2009 03:37
Как это связать с page faults?

Никак. FastMM может контролировать только ту память, которую Вы запрашиваете у него - GetMem и т.п. Память, выделенная помимо него, каким-нибудь LocalAlloc etc, им не контролируется.

>>>page faults = около 14 000 000

Скорее всего это означает интенсивный свопинг, во всяком случае другие причины лично мне не известны. А свопинг, в свою очередь, может косвенно свидетельствовать и о больших утечках памяти в Вашем приложении. Причем FastMM вполне может этих утечек не замечать. Во-первых, эта память может выделяться помимо него,  а во-вторых, она может вполне корректно освобождаться - но при завершении приложения.

16-01-2009 14:21
Добавил FastMM4.
В этом приложении происходят утечки памяти.
5-12 байт: Unknownx1
21-36 байт: TCriticalSection x 1

Как это связать с page faults?

Приложение зависает при значении page faults = около 14 000 000.
Я впервые сталкиваюсь с отладкой утечек памяти, поэтому прошу помочь, даже
в элементарных на первый взгляд вещах.

15-01-2009 18:51
Буду признателен за любую помощь.

15-01-2009 18:51
Кто-нибудь в курсе по поводу page faults?
Это единственное, что приходиться подозревать.
Очень внимательно пересмотрел структуру потоков.
Перечитал http://forum.vingrad.ru/forum/topic-60076.html
Может есть особенности в конструкциях try - except, при использовании их в потоках?

14-01-2009 01:46
Да нет, вроде как не потоки. Дело в том, что я отображаю изображения с жесткого диска. Их не много и когда последний из списка показан, программа отображает первый.
т.е. действия цикличны, а зависает программа по истечении произвольного количества времени.
Это приводит к мысли о воздействии внешних факторов (кол-во) свободной памяти, место на HDD, или кол-во доступной видео памяти.
Можно ли как-то проверить наличие не освобожденных указателей? Ведь при загрузки текстуры резервируется видеопамять...

14-01-2009 01:24
Не могу найти закономерности. Вероятнее всего, ошибка при организации многопоточной работы. Попробуйте запускать всё в одном потоке. Либо методом половинного деления: закомнтариваете половину кода, запускаете, смотрите есть ли ошибка. Если есть, закоментариваете половину оставшийся части. Если ошибка исчезла, значит она в последнем закоментированном участке...

Добавьте свое cообщение

Вашe имя:  [Войти]
Ваш адрес (e-mail):На Королевстве все адреса защищаются от спам-роботов
контрольный вопрос:
"Мы с тобой одной крови — ты и я!". Чьи это заветные слова?
в качестве ответа на вопрос или загадку следует давать только одно слово в именительном падеже и именно в такой форме, как оно используется в оригинале.
Надоело отвечать на странные вопросы? Зарегистрируйтесь на сайте.
Тип сообщения:
Текст:
Жирный шрифт  Наклонный шрифт  Подчеркнутый шрифт  Выравнивание по центру  Список  Заголовок  Разделительная линия  Код  Маленький шрифт  Крупный шрифт  Цитирование блока текста  Строчное цитирование
  • вопрос Круглого стола № XXX

  • вопрос № YYY в тесте № XXX Рыцарской Квинтаны

  • сообщение № YYY в теме № XXX Базарной площади
  • обсуждение темы № YYY Базарной площади
  •  
     Правила оформления сообщений на Королевстве

    Страница избранных вопросов Круглого стола.
      
    Время на сайте: GMT минус 5 часов

    Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter.
    Функция может не работать в некоторых версиях броузеров.

    Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
    Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

     
    © При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
    Все используемые на сайте торговые марки являются собственностью их производителей.

    Яндекс цитирования