Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2008.01.20;
Скачать: CL | DM;

Вниз

Утечка памяти, где засада?   Найти похожие ветки 

 
leonidus   (2007-12-18 20:29) [0]

Есть код:

procedure BtmRot(const B: TBitmap;fi:integer; var res:TBitmap);
type
 TRGBTripleArray = array[word] of TRGBTriple;
 pRGBTripleArray = ^TRGBTripleArray;
var
x0,y0,i,j,x1,y1,x11,y11,x2,y2:integer;
ht,wd,newht,newwd:integer;
cfi,sfi: double;
sline1,sline2: pRGBTRipleArray;
Result:TBitmap;
BEGIN
sfi:=sin(degtorad(fi));
cfi:=cos(degtorad(fi));
ht:=b.height;
wd:=b.width;
newwd:=abs(round(ht*sfi))+abs(round(wd*cfi));
newht:=abs(round(wd*sfi))+abs(round(ht*cfi));
Result:=TBitmap.create;
Result.Width:=newwd;
Result.Height:=newht;
Result.PixelFormat:=pf24bit;
x0:=wd div 2;
y0:=ht div 2;
for j :=newht-1 downto 0 do begin
 sline2 := Result.scanline[j];
 y1:= 2*(j-(newht-ht) div 2 -y0);
 for i := newwd-1 downto 0 do begin
   x1:=2*(i-(newwd-wd) div 2 -x0);
   x2 :=round(x1 * cfi - y1 * sfi);
   y2 :=round(x1 * sfi + y1 * cfi);
   x11:=x2 div 2 +x0;
   y11:=y2 div 2 +y0;
   if (x11>=0)and(x11<wd)and(y11>=0)and(y11<ht) then begin
     sline1 := b.scanline[y11];
     sline2[i] := sline1[x11];
   end;
 end;
end;

res:=result;
result.Free;
end;

код вращает заданный битмап на заданный угол и возвращает результат в другой битмап. Однако есть засада. Если не писать "result.Free;" то получаю утечку памяти, если писать, то AV. В чем же трабла?


 
Palladin ©   (2007-12-18 20:31) [1]

какой дурной тон в var параметрах возвращать значение объекта


 
leonidus   (2007-12-18 20:39) [2]

а как лучше сделать?


 
malyar   (2007-12-18 20:41) [3]

res:=result;
result.Free;
и
res.Free;
одно и тоже

а AV вы получаете при последующем обращении к res после выхода из проседуры


 
malyar   (2007-12-18 20:56) [4]

если есть желание погонять объект через VAR  то не создавай result ,а пользуйся res ,а создавай и убивай его за пределами процедуры


 
leonidus   (2007-12-18 21:17) [5]

malyar т.е. вы предлагаете сделать так:

procedure BtmRot(B: TBitmap;fi:integer);
type
 TRGBTripleArray = array[word] of TRGBTriple;
 pRGBTripleArray = ^TRGBTripleArray;
var
x0,y0,i,j,x1,y1,x11,y11,x2,y2:integer;
ht,wd,newht,newwd:integer;
cfi,sfi: double;
sline1,sline2: pRGBTRipleArray;
Result:TBitmap;
BEGIN
sfi:=sin(degtorad(fi));
cfi:=cos(degtorad(fi));
ht:=b.height;
wd:=b.width;
newwd:=abs(round(ht*sfi))+abs(round(wd*cfi));
newht:=abs(round(wd*sfi))+abs(round(ht*cfi));
Result:=TBitmap.create;
Result.Width:=newwd;
Result.Height:=newht;
Result.PixelFormat:=pf24bit;
x0:=wd div 2;
y0:=ht div 2;
for j :=newht-1 downto 0 do begin
 sline2 := Result.scanline[j];
 y1:= 2*(j-(newht-ht) div 2 -y0);
 for i := newwd-1 downto 0 do begin
   x1:=2*(i-(newwd-wd) div 2 -x0);
   x2 :=round(x1 * cfi - y1 * sfi);
   y2 :=round(x1 * sfi + y1 * cfi);
   x11:=x2 div 2 +x0;
   y11:=y2 div 2 +y0;
   if (x11>=0)and(x11<wd)and(y11>=0)and(y11<ht) then begin
     sline1 := b.scanline[y11];
     sline2[i] := sline1[x11];
   end;
 end;
end;

b:=result;
result.Free;
end;

?


 
Джо ©   (2007-12-18 21:30) [6]

2  leonidus  
Есть несколько общепринятых схем. Перечисляю в произвольном порядке.

1.
Объект передается в процедуру.
Создание объекта — до вызова процедуры.
Освобождение объекта — после вызова процедуры.
Пример:
Obj := TObj.Create;
try
 Proc (Obj);
 ...
finally
 Obj.Free;
end;


2. Объект создается и возвращается из процедуры через var-параметр.
Создание — в процедуре
Удаление — после вызова процедуры
Пример:
procedure Proc (var Obj: TObj);
begin
 Obj := TObj.Create;
 ....
end;

...
try
 Proc (Obj);
finally
 Obj.Free  
end;

3. Объект создается и возвращается из функции.
Создание — в функции.
Уничтожение — после вызова функции.
Пример:
function Proc: TObj;
begin
 Result := TObj.Create;
 ....
end;

...
try
 Obj := Proc;
finally
 Obj.Free  
end;


При использовании каждого способа следует четко понимать, кто создает и разрушает объект. И исходя из этого и конкретных нужд и выбирать способ.
Самый простой для понимания и сопровождения — способ (1). Так как создание и уничтожение объекта происходит на одном уровне иеарархии, «в одном месте». Что наглядно. И легко позволяет отследить утечки. Другие способы «распыляют» создание и уничтожение по разным уровням и потому, для начинающих я бы их не рекоммендовал.


 
Palladin ©   (2007-12-18 21:32) [7]


> [6] Джо ©   (18.12.07 21:30)

ай ай ай :)
дополнение к случаю 2 и 3.

procedure Proc (var Obj: TObj);
begin
Obj := TObj.Create;
....
end;

...
obj:=Nil;
try
Proc (Obj);
finally
Obj.Free  
end;


 
Efir   (2007-12-18 22:16) [8]

А зачем (var p:TBitmap) если объект класса TBitmap и так указатель?


 
homm ©   (2007-12-18 22:19) [9]

> [8] Efir   (18.12.07 22:16)

А вдруг нужно изменить сам указатель, не только объект, на который он ссылается?


 
Palladin ©   (2007-12-18 22:19) [10]

с добрым утром


 
Джо ©   (2007-12-18 22:46) [11]

> [7] Palladin ©   (18.12.07 21:32)
>
> > [6] Джо ©   (18.12.07 21:30)
>
> ай ай ай :)
> дополнение к случаю 2 и 3.
>
> procedure Proc (var Obj: TObj);
> begin
> Obj := TObj.Create;
> ....
> end;
>
> ...
> obj:=Nil;
> try
> Proc (Obj);
> finally
> Obj.Free  
> end;

Угумсь.


 
Джо ©   (2007-12-18 22:48) [12]

> [8] Efir   (18.12.07 22:16)
> А зачем (var p:TBitmap) если объект класса TBitmap и так
> указатель?

А затем, что этот способ (var O: TObj) именно и предназначен для того, чтобы возвращать наружу созданный внутри экземпляр. Как правило, туда внутрь ничего и не передают, за исключением случая, упомянутого [7] Palladin.


 
Efir   (2007-12-19 00:13) [13]


> Джо ©   (18.12.07 22:48) [12]


И чем это может грозить? Или это плохой тон в пограммировании?


 
Джо ©   (2007-12-19 00:41) [14]

> [13] Efir   (19.12.07 00:13)
>
> > Джо ©   (18.12.07 22:48) [12]
>
>
> И чем это может грозить? Или это плохой тон в пограммировании?

Плохой тон? Просто этот способо чуть более потенциально-опасный, чем способ, когда передается ссылка на уже созданный объект. Есть такое правило — создавать и уничтожать объекты на одном «уровне». Здесь оно нарушается. Иногда его используют, но я, честно говоря, не вижу в нем никаких преимуществ, всегда можно обойтись без него.


 
leonidus   (2007-12-20 13:25) [15]

Всем спасибо, вроде все получилось.



Страницы: 1 вся ветка

Текущий архив: 2008.01.20;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.029 c
15-1197881863
@!!ex
2007-12-17 11:57
2008.01.20
Вэйвлет(Wavelet)


6-1178792527
Виктор007
2007-05-10 14:22
2008.01.20
Проверить на 404 ошибку


15-1197727186
turbouser
2007-12-15 16:59
2008.01.20
Хоккей


15-1197652299
Wolf
2007-12-14 20:11
2008.01.20
Вопрос на тему написание программы для создания Backup системы


2-1198361464
Embargo
2007-12-23 01:11
2008.01.20
Без ошибки