Форум: "Начинающим";
Текущий архив: 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.052 c