Форум: "Основная";
Текущий архив: 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