Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2008.01.20;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.49 MB
Время: 0.71 c
2-1198075271
Kerk
2007-12-19 17:41
2008.01.20
Про Excel


2-1198219963
LexXL
2007-12-21 09:52
2008.01.20
проверить наличие файла на ftp


6-1178194098
Lobach
2007-05-03 16:08
2008.01.20
Отправка данных скрипту


15-1197452705
DelphiN!
2007-12-12 12:45
2008.01.20
Алгоритм вычисления, максимального колличества пересечений времен


15-1197825737
Lip
2007-12-16 20:22
2008.01.20
Ряд Тэйлора





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский