Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 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
2-1145359027
sksyat
2006-04-18 15:17
2006.05.07
IdSMTP


5-1130827877
JohnKorsh
2005-11-01 09:51
2006.05.07
Как позиционировать курсор в Memo и в RichEdit?


15-1144838450
Kolan
2006-04-12 14:40
2006.05.07
Сайт www.almportal.ru - мертвый что ли?


2-1145557478
Ded22
2006-04-20 22:24
2006.05.07
Locate ???


1-1143799518
Andreus
2006-03-31 14:05
2006.05.07
Как получить расширение файла открываемого OpenDialog1.FileName





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