Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Программа "ест" память, потом сбой


Pcrepair ©   (2011-06-30 17:58:00) 

Добрый день
Программа была написана для проверки работоспособности процедур компресии-декомпресии графического файла с использованием Zlib в Делфи2010

unit main;
interface
uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, ExtCtrls, StdCtrls, Zlib;
type
 TForm1 = class(TForm)
   Button1: TButton;
   Image1: TImage;
   procedure Button1Click(Sender: TObject);
   procedure Compress;
   procedure DCompress;
 private
   { Private declarations }
 public
   { Public declarations }
 end;
var
 Form1: TForm1;
 pic1: TMemoryStream;
 pic2: TMemoryStream;
 pic3: TMemoryStream;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject); //при нажатии на кнопку
begin
 if FileExists(ExtractFilePath(Application.ExeName)+'\'+'s1.bmp') then
         DeleteFile(ExtractFilePath(Application.ExeName)+'\'+'s1.bmp');//удаляется файл
 pic1 := TMemoryStream.create;//создаются потоки
 pic2 := TMemoryStream.create;
 pic3 := TMemoryStream.create;
 pic1.LoadFromFile(ExtractFilePath(Application.ExeName)+'\'+'s.bmp');//в поток загружается файл с диска
 Compress;//файл сжимается  и передается в ПЕРЕМ pic2
 DCompress;//файл декомпрессируется и передается в pic3
 pic3.SaveToFile(ExtractFilePath(Application.ExeName)+'\'+'s1.bmp');//файл сохраняется на диск
 Image1.Picture.bitmap.LoadFromFile(ExtractFilePath(Application.ExeName)+'\'+'s1.bmp');//файл отображается в окне, для контроля

 pic1.Free;//уничтожение ПЕРЕМ
 pic2.Free;
 pic3.Free;

 end;

procedure TForm1.Compress;//процедура сжатия, не мое
var
 TmpStream : TMemoryStream;
 CmpStream : TCompressionStream;
begin
 TmpStream := TMemoryStream.Create;
 CmpStream := TCompressionStream.Create (clMax, TmpStream);
// application.ProcessMessages;
 pic1.Seek (0, 0);
 CmpStream.CopyFrom (pic1, pic1.Size);
 CmpStream.Free;
//  FCompressionRate := 100 - TmpStream.Size / _in.Size * 100;
 TmpStream.Position:=0;
 pic2.Position:=0;
 pic2.SetSize(TmpStream.Size);
 pic2.CopyFrom (TmpStream, TmpStream.Size);
 TmpStream.Free;
end;

procedure TForm1.DCompress;// процедура декомпресии, не мое
const
 BufSize = 1024;
var
 Buf : pointer;
 Readed : Integer;
 FDecompressedStream:TMemoryStream;
 DecompStream : TDecompressionStream;
begin
     pic2.Seek (0, 0);
       DecompStream := TDecompressionStream.Create(pic2);
       try
           FDecompressedStream := TMemoryStream.Create;
           GetMem (Buf, BufSize);
           try
             repeat
               Readed := DecompStream.read (Buf^, BufSize);
               if Readed > 0
                 then FDecompressedStream.Write (Buf^, Readed);
             until Readed <= 0;
           finally
             FreeMem (Buf, BufSize);
           end;
       finally
         DecompStream.Free;
       end;
       FDecompressedStream.Seek (0, 0);
       pic3.Seek (0, 0);
       pic3.CopyFrom(FDecompressedStream, FDecompressedStream.Size);
end;
end.


В общем программа работает, но при каждом нажатии на кнопку отбирает все больше памяти(4-12-20- и далее мб)
Все Переменные после использования уничтожаются
В чем может быть проблема?


Pcrepair   (2011-07-01 20:29:00) [1]

Ega23, на самом деле работает это:

var
 Form1: TForm1;
 Stream: TMemoryStream;

implementation

{$R *.dfm}

procedure TForm1.CompressStream();
var
pOut: Pointer;
outSize: Integer;
begin
ZCompress(Stream.Memory, Stream.Size, pOut, outSize, zcMax);
try
 Stream.Clear;
 Stream.WriteBuffer(pOut^, outSize);
 finally
  FreeMem(pOut);
end;
end;

procedure TForm1.DecompressStream;
var
pOut: Pointer;
outSize: Integer;
begin
ZDecompress(Stream.Memory, Stream.Size, pOut, outSize);
try
    Stream.Clear;
  Stream.WriteBuffer(pOut^, outSize);
finally
  FreeMem(pOut);
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
appDir: string;
begin
Stream := TMemoryStream.Create;
try
  appDir := ExtractFilePath(ParamStr(0));
  Stream.LoadFromFile(appDir+'s.bmp');
  CompressStream;
  DecompressStream;
  Stream.Position := 0;
  Image1.Picture.bitmap.LoadfromStream(Stream);
finally
  Stream.Free;
end;
end;

end.

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


Игорь Шевченко   (2011-07-01 16:57:00) [2]


> а чего - Ega забанили?


а чего, правила читать - не судьба ? :)
Забанили.


antonn   (2011-07-01 16:47:00) [3]

а чего - Ega забанили? я думал он об авторе говорил :))


Игорь Шевченко   (2011-07-01 16:37:00) [4]

Ega23 ©   (01.07.11 10:25) [9]

Небольшая коррекция кода в [9]: строки

  Stream.Position := 0;

следует заменить на

  Stream.Clear;

(от автора [9])


Pcrepair   (2011-07-01 16:05:00) [5]

будем пробовать


Dennis I. Komarov   (2011-07-01 13:25:00) [6]


> Уверен?

Да ладно, пятницу тяжко переживает поди...
дня на три :)


antonn   (2011-07-01 13:18:00) [7]


> не узнаешь свой код?
> это по твоей наводке из файла p_u.pas

тогда по той же наводке попробуй использовать UnPack_Memory(var _in:TMemoryStream);, а не это нагромождение


Anatoly Podgoretsky   (2011-07-01 11:41:00) [8]

> Ega23  (01.07.2011 10:25:09)  [9]

Уверен?


Ega23   (2011-07-01 10:25:00) [9]


procedure CompressStream(Stream: TMemoryStream);
var
 pOut: Pointer;
 outSize: Integer;
begin
 ZCompress(Stream.Memory, Stream.Size, pOut, outSize, zcMax);
 try
   Stream.Position := 0;
   Stream.WriteBuffer(pOut^, outSize);
 finally
   FreeMem(pOut);
 end;
end;

procedure DecompressStream(Stream: TMemoryStream);
var
 pOut: Pointer;
 outSize: Integer;
begin
 ZDecompress(Stream.Memory, Stream.Size, pOut, outSize);
 try
   Stream.Position := 0;
   Stream.WriteBuffer(pOut^, outSize);
 finally
   FreeMem(pOut);
 end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 ms: TMemoryStream;
 appDir: string;
begin
 ms := TMemoryStream.Create;
 try
   appDir := ExtractFilePath(ParamStr(0));
   ms.LoadFromFile(appDir+'s.bmp');
   CompressStream(ms);
   DecompressStream(ms);
   ms.Position := 0;
   Image1.Picture.bitmap.LoadfromStream(ms);
 finally
   ms.Free;
 end;
end;


Как же мне это всё надоело... Забаньте на месяц, что-ли?


Pcrepair   (2011-07-01 08:20:00) [10]

не узнаешь свой код?
это по твоей наводке из файла p_u.pas


antonn   (2011-07-01 00:02:00) [11]


> procedure TForm1.DCompress;// процедура декомпресии, не
> мое

а чье?


Ega23   (2011-06-30 21:44:00) [12]


> и чем канкретна код ужасен?


Ну например:
1. В событии OnFormCreate пропиши ReportMemoryLeaksOnShutdown := True;
2. Переименуй файл s.bmp в _s.bmp.
3. Запусти приложение
4. Нажми на кнопку
5. Прочитай ExceptionMessage
6. Штатно закрой приложение (не через Program Reset)
7. Промедитируй над сообщением, которое вывалится.


Pcrepair   (2011-06-30 21:09:00) [13]

и чем канкретна код ужасен?


Ega23   (2011-06-30 19:59:00) [14]

Несколько советов по улучшению кода:
1. Используй ZCompress и ZDecompress. В стримах под D2010 есть косяк, я уже раньше писал.
2. В данном примере можно обойтись одним стримом, вместо трёх. Просто добавь в свои методы Compress и Decompress параметр Stream: TMemoryStream
3. Используй Stream.ReadBuffer и Stream.WriteBuffer.
4. Пользуйся конструкцией:
 obj := TSomeObject.Create;
 try
   /// Работа с obj
 finally
   obj.Free;
 end;


Ega23   (2011-06-30 19:43:00) [15]

Ну вот видишь, всё просто.

З.Ы. Код - ужасен.


Pcrepair   (2011-06-30 19:06:00) [16]

да че тут искать?
       FDecompressedStream.Free;


Ega23   (2011-06-30 18:45:00) [17]


> В чем может быть проблема?


В процедуре DCompress утечка памяти. Это то, что "блондинка" сходу увидел а.
Но подсказывать не буду. Из принципа. :)
Не из вредности, а потому, что ты её должен найти сам.


Наверх

Титульная страница Поиск, карта сайта Написать письмо