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

Вниз

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

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

Наверх





Память: 0.48 MB
Время: 0.004 c
1-1126287500
Pavel__
2005-09-09 21:38
2005.10.02
А что представляет из себя переменная типа string


1-1126031771
Дмитрий_05
2005-09-06 22:36
2005.10.02
Создать кнопку TabbedNotebook


3-1124268309
PP
2005-08-17 12:45
2005.10.02
Групировка в dxDBGrid1


1-1125926628
Mishenka
2005-09-05 17:23
2005.10.02
Копирование текста в Clipboard


1-1126162964
Zloj
2005-09-08 11:02
2005.10.02
Как получить значение возвроўаемое софтом?





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский