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

Вниз

Освобождение памяти   Найти похожие ветки 

 
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;
Скачать: CL | DM;

Наверх




Память: 0.54 MB
Время: 0.029 c
5-1130227678
DimaBr
2005-10-25 12:07
2006.05.07
Редакторы компонент


2-1145365419
kyn66
2006-04-18 17:03
2006.05.07
Порядковый номер дня в году


3-1142251799
Shlomo
2006-03-13 15:09
2006.05.07
Найти следующую запись?


2-1145304765
qazwsx
2006-04-18 00:12
2006.05.07
Чёт не получается у мну нормально с мускулом работать...


15-1144765470
Tirael
2006-04-11 18:24
2006.05.07
буква диска и пути