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

Вниз

утечка памяти   Найти похожие ветки 

 
Цукор 5   (2005-09-12 19:42) [0]

В продолжении ветки http://delphimaster.net/view/1-1126429711/. Итак,имеется код(для простоты я всё сделал без DLL) :

type
TMyRetVal=record
Line1:ShortString;
Line2:ShortString;
Dept : Byte;
end;

type
PMyRetVal = ^TMyRetVal;

function GetVal(Inp1,Inp2:Integer;Q:PMyRetVal):Boolean;
 var I:Integer;
begin
 Randomize;
 for I:=Inp1 to Inp2 do
 begin
   Q^.Line1:="Line1_"+IntToStr(I);
   Q^.Line2:="Line2_"+IntToStr(I);
   Q^.Dept :=random(9);
   Inc(Q);
 end;
 Result:=True;
end;

procedure TForm1.Button1Click(Sender: TObject);
var Q:PMyRetVal;
 I:Integer;
 Inp1,Inp2:Integer;
begin
 Inp1:=1;
 Inp2:=842;
 GetMem(Q,(Inp2-Inp1+1)*SizeOf(TMyRetVal));
 GetVal(Inp1,Inp2,Q);

 for i:=0 to (Inp2-Inp1) do
 begin
   Memo1.Lines.Add(Q^.Line1);
   Memo1.Lines.Add(Q^.Line2);
   Memo1.Lines.Add(IntToHex(Q^.Dept,2));
   Inc(Q);
 end;
 Q:=nil;// без нее AV! Хотя,я думаю в этом и беда :(
 FreeMem(Q);
end;


Получаю утечку памяти на все длинну структуры :( Какие будут предложения?


 
Цукор 5   (2005-09-12 19:44) [1]

Опс...структура вот такая :

type
TMyRetVal=record
Line1:String[25];
Line2:String[25];
Dept : Byte;
end;

Она меньше весит,все же.


 
AlexWlad ©   (2005-09-12 19:50) [2]


Q:=nil;// без нее AV! Хотя,я думаю в этом и беда :(
FreeMem(Q);


Во-первых - сначала FreeMem, и только потом МОЖНО (но не обязательно) :=nil.
А самое главное - ты в цикле делаешь Inc(Q);, тем самым изменяя адрес начала выделенного блока памяти. Так что все в норме.


 
Anatoly Podgoretsky ©   (2005-09-12 19:56) [3]

Это означает, что и утечка и AV закономерны.


 
Цукор 5   (2005-09-12 20:16) [4]

2 AlexWlad ©   (12.09.05 19:50) [2]
>Во-первых - сначала FreeMem, и только потом МОЖНО (но не обязательно) :=nil.

Не получается. Я же написал в комментариях. Если без Q:=nil; а сразу FreeMem(Q); то Invalid Pointer Operation.

2 Anatoly Podgoretsky ©   (12.09.05 19:56) [3]
Мне непонятны Ваши слова. Предложения по сабжу будут???


 
AlexWlad ©   (2005-09-12 20:37) [5]

Цукор 5   (12.09.05 20:16) [4]

Invalid Pointer Operation у тебя из-за "...в цикле делаешь Inc(Q);, тем самым изменяя адрес начала выделенного блока памяти...". Тебе надо завести 2 переменных типа PMyRetVal, второй переменной присвоить значение первой после гетмем и использовать ее в цикле. Таким образом, ты не теряешь адрес блока памяти. И в конце - FreeMem (nil - по вкусу). Цикл имеется в виду в обработчике кнопки.


 
Цукор 5   (2005-09-12 20:43) [6]

2 AlexWlad ©   (12.09.05 20:37) [5]
Спасибо,догнал ;) Сделал так :
for i:=0 to  (Inp2-Inp1) do Dec(Q);


 
Ihor Osov'yak ©   (2005-09-12 20:45) [7]

2 Цукор 5

Подсказка намбер ван:
Подумайте, что делает function GetVal... Наводящая подсказка - изменится эффект от работы этой функции, если вместо Inp2:=842;
написать Inp2:=248; (я не имею ввиду количестов выполнений тела цикла внутри функции).

Теперь по существу.
в procedure TForm1.Button1Click на втором прохождении цикла (после того, как будет выполнено Inc(Q);) по Q^.Line1 и Q^.Line2 будет идти обращение к областям памяти, где вместо короткой строки будет находится мусор. Код будет пытаться преобразовать этот мусор к AnsiString, и первый этап будет состоять в поиске терминального зеро-символа (так как предполагается все же наличие строки, а не мусора). Не факт, что этот символ будет присутствовать. И как следствие в процессе поиска будет сделана попытка чтения по адресу за пределами распределенной памяти. Следствие этого следствия - исключение.
Но это вероятностный сценарий. Если эттого не произодет, то случится неминуемо следующее:

Q:=nil;// без нее AV! Хотя,я думаю в этом и беда :
FreeMem(Q); - понятно, что здесь ничего не освобождается, так как Q уже nil. Как следствие  - утечка.

Если же убрать Q:=nil - то нужно вспомнить, что Q вследствие наличия Inc(Q); в теле цікла уже будет за пределами распределенной памяти. А это гарантированное исключение.


 
Ihor Osov'yak ©   (2005-09-12 20:46) [8]

2 [6] Цукор 5   (12.09.05 20:43)

а случайно вычисление типа 2+2 посредством написания цикла осуществлять не приходилось?


 
Ihor Osov'yak ©   (2005-09-12 20:49) [9]

относительно [7] Ihor Osov"yak ©   (12.09.05 20:45)

в function GetVal...  не заметил inc(Q) - прошу извинить. Замечание относительно инициализации только первого элемента буфера снимается :-).

Но. Все же иззбегайте такого стиля написания кода.


 
Неважно   (2005-09-12 21:43) [10]

2 Ihor Osov"yak ©  
> Все же иззбегайте такого стиля написания кода.
Покажите как надо. Буду очень благодарен ;)


 
Цукор 5   (2005-09-12 21:55) [11]

2 Ihor Osov"yak ©   (12.09.05 20:46) [8]
>а случайно вычисление типа 2+2 посредством написания цикла осуществлять не приходилось?

Уже и пошутить нельзя...

Dec(Q,Inp2-Inp1+1);


 
Ihor Osov'yak ©   (2005-09-12 22:01) [12]

2 [10] Неважно   (12.09.05 21:43)

Один из вариантов:

type
 TMyRetVal = record
   Line1: ShortString;
   Line2: ShortString;
   Dept: Byte;
 end;
 PMyRetValArray = ^TMyRetValArray;
 TMyRetValArray = array[0..$FFFFF] of TMyRetVal;

function GetVal(aLen: integer; aArr: PMyRetValArray): Boolean;
var
 idx: Integer;
begin
 //Randomize; - рандомайз желательно использовать только один раз, например в секции инициализации
 for idx := 0 to aLen - 1 do
   with aArr[idx] do
   begin
     Line1 := "Line1_" + IntToStr(idx);
     Line2 := "Line2_" + IntToStr(idx);
     Dept := random(9);
   end;
 Result := True;
end;


некоторые дополнительные расходы, связанные с типизацией (только время на написание нескольких строчек) с лихвой окупаются более прозрачным кодом.



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

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

Наверх




Память: 0.5 MB
Время: 0.05 c
3-1124689916
syte_ser78
2005-08-22 09:51
2005.10.02
Два сетевых подключения к базе paradox


6-1117745556
Delphi_is_cool
2005-06-03 00:52
2005.10.02
Объекты виндовс


1-1126379116
Grol
2005-09-10 23:05
2005.10.02
Поставить окно приложения на передний план


3-1124258621
PChI
2005-08-17 10:03
2005.10.02
Описание dxdbgrid


14-1126253582
ocean
2005-09-09 12:13
2005.10.02
Распайка USB 2