Форум: "Начинающим";
Текущий архив: 2006.05.07;
Скачать: [xml.tar.bz2];
ВнизОсвобождение памяти Найти похожие ветки
← →
KygECHuK © (2006-04-14 20:21) [0]При освобождении памяти, занятой при помощи функций GetMem или StrAlloc иногда у меня возникает ошибка доступа памяти. В чём может скрываться ошибка ?
← →
Desdechado © (2006-04-14 20:37) [1]да в чем угодно:
1. неверный адрес
2. неверный размер
3. выделяем одним, освобождаем несовместимой функцией
4. память там уже освобождена
5. т.п.
← →
Rial © (2006-04-14 20:45) [2]Очень вероятна ситуация:
Выделяешь память под массив или другую структуру.
При работе обращаешься по арресу, большему допустимого, из-за чего при освобождении гарантированно возникнет ошибка.
Type TV=Array[0..0]of Byte;
pTV=^TV;
...
Var pV:pTV;
begin
GetMem(pV,40);
pV^[100]:=11;//Это, скрорее всего, прокатит.
...
FreeMem(ptV[,40]);//Вот тут возникнет ошибка.
end;
← →
Gero © (2006-04-15 01:47) [3]> да в чем угодно
Поддерживаю.
← →
KygECHuK © (2006-04-18 09:51) [4]>> Desdechado © (14.04.06 20:37) [1]
>> да в чем угодно:
>>1. неверный адрес
Адресс верный, записан, проверен.
>>2. неверный размер
Размер верен, записан, проверен для Getmem, а в StrAlloc он хранитсся в пямяти до массива
>>3. выделяем одним, освобождаем несовместимой функцией
Для GetMem - FreeMem, а для StrAlloc - StrDispose
>>4. память там уже освобождена
Непосредственнно перед освобождением происходит работа с массивом
>> FreeMem(ptV[,40]);//Вот тут возникнет ошибка.<< еще бы :)
Исследовав проблему я пришел к выводу, что при выделении больших объёмов памяти ошибки происходят чаще.
← →
Anatoly Podgoretsky © (2006-04-18 10:02) [5]Тогда должно работать.
← →
KygECHuK © (2006-04-18 10:12) [6]А вот на тебе Acces Violation в самый интересный момент - сиди думай. Уже месяц жизни потратил на выяснении причины. Короче дело обстоит так:
я использую буффер памяти, очень часто меняя его длинну. При очередной смене длинны появляется вышеупомянатая ошибка.
И почему ошибка появляется стабильно при выделении больши объёмов памяти до 3 Mb ?
Прочитал о MemoryManager - ответа нет.
← →
Плохиш © (2006-04-18 10:16) [7]Надо исправить ошибку в 17й строке.
← →
Сергей М. © (2006-04-18 10:24) [8]
> использую буффер памяти, очень часто меняя его длинну
В ряде случаев смена размера буфера, распределяемого динамически, ведет к смене адреса начала буфера. При реаллокации буфера с целью увеличения его размера полагаться на прежний адрес буфера нельзя.
← →
KygECHuK © (2006-04-18 10:35) [9]Я не ссылайсь на прежний адресс буфера. Я тупо освобождаю память из под буффера и беру новый адресс с новой длинной. Вот в момент освобождения происходит ошибка.
← →
Сергей М. © (2006-04-18 10:47) [10]
> KygECHuK © (18.04.06 10:35) [9]
Показывай код
← →
Anatoly Podgoretsky © (2006-04-18 11:06) [11]KygECHuK © (18.04.06 10:35) [9]
Тебе же указали точное место ошибки - 17 строка.
← →
balepa © (2006-04-18 11:09) [12]KygECHuK © не все же KygECHuK"и и магией пользоваться не умеют что бы узнать что ты там написал
← →
KygECHuK © (2006-04-18 11:29) [13]пример немного другоу но проблема та же:
function ChangeFileVers(FileName: string; Ma, Mi, Re, Bu: word): integer;
const
Signature = 281479253787837;
var
filestream : TFileStream;
i,l,pos1 : Integer;
Ver : Array[1..4] of word;
Fstr : String;
P : Pchar;
FSize : Integer;
begin
begin
Result := 0;
if not FileExists(FileName) then
begin
Result := -2;
exit;
end;
try
filestream := TFileStream.Create(FileName,fmOpenReadWrite);
p := pointer(StrAlloc(filestream.Size + 1));
try
filestream.Read(pointer(p)^, filestream.Size);
pos1 := -1;
FSize := filestream.Size;
l := filestream.Size - 9;
for i := 0 to l do
if (int64(pointer(@P[i])^) = int64(pointer(@P[i + 8])^)) and
(int64(pointer(@P[i])^) <> 0) and ((int64(pointer(@p[i - 8])^)) = Signature) then
begin
if pos1 <> -1 then
begin
Result := -1;
exit;
end;
pos1 := i;
Result := 0;
end;
Ver[1] := Ma;
Ver[2] := Mi;
Ver[3] := Re;
Ver[4] := Bu;
Fstr := Fstr + pchar(@Ver)[2] + pchar(@Ver)[3] ;
Fstr := Fstr + pchar(@Ver)[0] + pchar(@Ver)[1] ;
Fstr := Fstr + pchar(@Ver)[6] + pchar(@Ver)[7] ;
Fstr := Fstr + pchar(@Ver)[4] + pchar(@Ver)[5] ;
Fstr := Fstr + pchar(@Ver)[2] + pchar(@Ver)[3] ;
Fstr := Fstr + pchar(@Ver)[0] + pchar(@Ver)[1] ;
Fstr := Fstr + pchar(@Ver)[6] + pchar(@Ver)[7] ;
Fstr := Fstr + pchar(@Ver)[4] + pchar(@Ver)[5] ;
CopyMemory(pointer(@P[pos1]), pointer(pchar(Fstr)),16);
filestream.Position := 0;
filestream.Size := 0;
filestream.Write(pointer(p)^, FSize)
finally
filestream.Free;
StrDispose(pointer(P)); // Вот тут появляется ошибка при работе
//с больши файлами. Понимаю, что код можно
//было сделать более оптимальным, но я ищу
//причину ошибки при освобождении больших
//объёмов памяти
end;
except
Result := GetLastError;
end;
end;
end;
← →
Сергей М. © (2006-04-18 11:59) [14]Ну и где здесь "смена длины" ?
Смена длины - это realloc-операция, а у тебя ее нигде нет. Так что в заблуждение вводишь ..
> тупо освобождаю память
Надо бы не "тупо освобождать", а под отладчиком внимательно сравнить значение p, полученное при StrAlloc, со значением p, передаваемым в StrDispose. Для начала хотя бы ..
← →
KygECHuK © (2006-04-18 12:02) [15]Удалено модератором
Примечание: Создание пустых сообщений
← →
KygECHuK © (2006-04-18 12:06) [16]ReAlloc пока забыли. ситуация состоит в следующем:
при малых размерах файла программа не выдаёт ошибок, а при больших - выдаёт. Вопрос - ПОЧЕМУ !?
← →
Сергей М. © (2006-04-18 12:06) [17]Есть подозрение, что где-то между StrAlloc и StrDispose ты гадишь в стеке, где хранится в т.ч. значение p. И подозрение это падает, скорей всего, на CopyMemory().
← →
Сергей М. © (2006-04-18 12:08) [18]
> Вопрос - ПОЧЕМУ !?
Потому что потому.
Отладчиком пользоваться не пробовал ?
Еше раз : первое что следует сделать для поиска ошибки - это сравнить значение p, полученное при StrAlloc, со значением p, передаваемым в StrDispose
← →
KygECHuK © (2006-04-18 12:10) [19]>> Сергей М.
>> Есть подозрение, что где-то между StrAlloc и StrDispose ты гадишь в стеке
Нет, программа удачно копирует содержимое из памяти в файл после CopyMemory()
← →
KygECHuK © (2006-04-18 12:22) [20]Адский сатанизм, щас ошибка не появляется, но я уверен она как всегда выскочит в самый неблагоприятный момент. Так было всегда
← →
Сергей М. © (2006-04-18 12:30) [21]Хорошо, ну тогда на основании чего ты сделал умозаключение о возникновении отказа именно при выполнении StrDispose() ?
← →
KygECHuK © (2006-04-18 12:45) [22]Когда ошибка появлялась я исследовал код отладчиком и именно строка с StrDispose оказалась причиной этого.
Завтра я постараюсь раздабыть тод код на каторой я жаловался в самом начале, но там ошибка такая же.
← →
KygECHuK © (2006-04-18 12:45) [23]Удалено модератором
← →
KygECHuK © (2006-04-18 12:45) [24]Удалено модератором
Примечание: Создание пустых сообщений
← →
GrayFace © (2006-04-18 16:35) [25]А зачам, вообще, использовать StrAlloc и StrDispose? Чем, например, GetMem не угодил? Или обычные строки/дин. массивы?
> if (int64(pointer(@P[i])^) = int64(pointer(@P[i + 8])^)) and
> (int64(pointer(@P[i])^) <> 0) and ((int64(pointer(@p[i - 8])^)) = Signature) then
Несабжевая ошибка: если i=0 и первые два условия выполнены, залезешь в p-8.
← →
Сергей М. © (2006-04-18 16:41) [26]
> GrayFace © (18.04.06 16:35) [25]
> первые два условия выполнены
Сомневаюсь что при i = 0 это условие когда-либо было бы выполнено ..
Да и AV тот самый возник бы (но вовсе необязательно) на этом операторе, который заведомо раньше по тексту, чем StrDispose(), именно на который столь упорно жалуется автор.
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2006.05.07;
Скачать: [xml.tar.bz2];
Память: 0.52 MB
Время: 0.011 c