Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

выделение памяти с ошибкой [D7, Win2k, WinXP]


Arm79 ©   (2007-02-02 12:54:00) 

Имеются следующие описания типов:

 PRow = ^TRow;
 TRow = packed record
   FldCount: Byte;
   RowLen: Integer;
   RowData: record end;
 end;

 PTable = ^TTable;
 TTable = record
   Ref: Integer;
   RowCount: Integer;
   TblData: TRow;
 end;


Процедура:

procedure TList.LoadFromBuffer(Buffer: PChar; var Position: integer): boolean;
 var
   i    : integer;
   Table: PTable;
   Row  : PRow;
   BA   : TByteArray; // array of byte

begin
 Table := PTable(Buffer);  // первые 8 байт это поля Ref и RowCount
 for i := 0 to Table.RowCount-1
 do begin
   GetMem(Row, SizeOf(TRow));  // почему то на этой строчке возникает Exception с сообщением access violation по такому то адресу. Причем каждый раз на 5 итерацию. RowCount > 250

   Row^.FldCount := ReadByte(Buffer, Position); // читает 1 байт
   Row^.RowLen   := ReadInt4(Buffer, Position); // читает 4 байта

   BA := ReadBytes(Buffer, Row^.RowLen, Position);
   System.Move(BA[0], Row^.RowData, Length(BA));

   Add(Row);
 end;
end;


При каких условиях GetMem (как и AllocMem) может выдавать ошибку?


Сергей М.   (2007-02-02 14:20:00) [1]


> У вас очень интересная реализация


Что же там интересного ? Тривиальная задача, тривиальный же код ..


Arm79   (2007-02-02 13:59:00) [2]

Большое спасибо, не думал, что пойдете на трату своего времени для демонстрации )

Мне был важен принцип, дальше я сам сделал бы. У вас очень интересная реализация, приму на заметку.


Сергей М.   (2007-02-02 13:55:00) [3]

procedure ReadBytes(DataIn, DataOut: PChar; Count: integer; var Position: integer);
var
  i:integer;
begin
for i := 0 to Count-1 do begin
  DataOut[i] := ReadByte(DataIn, Position);
end;

procedure TList.LoadFromBuffer(Buffer: PChar; var Position: integer): boolean;
var
  i    : integer;
  Table: PTable;
  Row  : PRow;
  tmpFldCount, tmpRowLen: Integer;
begin
Table := PTable(Buffer);
for i := 0 to Table.RowCount-1 do begin
  tmpFldCount := ReadByte(Buffer, Position); // читает 1 байт
  tmpRowLen   := ReadInt4(Buffer, Position); // читает 4 байта
  GetMem(Row, SizeOf(TRow) + tmpRowLen);  
  Row.FldCount := tmpFldCount;
  Row.RowLen   := tmpRowLen;
  ReadBytes(Buffer, @Row.RowData, Position);
  Add(Row);
end;
end;


Arm79   (2007-02-02 13:34:00) [4]


> Anatoly Podgoretsky ©   (02.02.07 13:31) [12]
> > Arm79  (02.02.2007 13:25:08)  [8]
>
> > то есть выделяю память равную 5, а потом к этой области
> памяти дописываю кусок
>
> Зачем ты так делаешь?


потому что руки кривые

поэтому и на форуме, уму разуму набираюсь


Anatoly Podgoretsky   (2007-02-02 13:34:00) [5]

>   ()  []

> как выделить память под поле RowData?

Это не имеет смысла дела, поскольку данное поле нулевой длины.


Сергей М.   (2007-02-02 13:32:00) [6]


> я лично вижу в памяти как
> BIIIIDDDDDD...DDDDD // byte, integer, data
>


Все правильно.
Своим "дописанным" DDDDDD...DDDDD ты изгадил содержимое некоего участка памяти, тебе не принадлежащего. И вполне возможно, что в этом участке лежат внутренние данные менеджера памяти, ты их беспардонно покоцал, поэтому менеджер и дает тебе отлуп в виде AV.


Anatoly Podgoretsky   (2007-02-02 13:31:00) [7]

> Arm79  (02.02.2007 13:25:08)  [8]

> то есть выделяю память равную 5, а потом к этой области памяти дописываю кусок

Зачем ты так делаешь?


Arm79   (2007-02-02 13:30:00) [8]

тогда просьба )

как выделить память под поле RowData?


Сергей М.   (2007-02-02 13:28:00) [9]


> выделяю память равную 5, а потом к этой области памяти дописываю
> кусок


Куда дописываешь-то ? В память, которую ты не выделял ? Это же нонсенс)


Arm79   (2007-02-02 13:26:00) [10]


> Сергей М. ©   (02.02.07 13:22) [6]
>
> > TByteArray; // array of byte
>
>
> А зачем ты использовал идентификатор TByteArray ? Он уже
> определен в SysUtils  как статический массив !


SysUtils в модулях идет раньше моего, поэтому TByteArray не является статическим и используется мое описане типа


Arm79   (2007-02-02 13:25:00) [11]

правильно.

тип

TRow = packed record
  FldCount: Byte;
  RowLen: Integer;
  RowData: record end;
end;


я лично вижу в памяти как
BIIIIDDDDDD...DDDDD // byte, integer, data

то есть выделяю память равную 5, а потом к этой области памяти дописываю кусок

System.Move(BA[0], Row^.RowData, Length(BA));


Сергей М.   (2007-02-02 13:24:00) [12]

+ см. palva ©   (02.02.07 13:22) [5]


Сергей М.   (2007-02-02 13:22:00) [13]


> TByteArray; // array of byte


А зачем ты использовал идентификатор TByteArray ? Он уже определен в SysUtils  как статическиймассив !


palva   (2007-02-02 13:22:00) [14]

> GetMem(Row, SizeOf(TRow));
Здесь SizeOf(TRow) равно 5. Т. е. вы не выделяете память под RowData ?


Arm79   (2007-02-02 13:17:00) [15]

Это суперконструкция из API, поставляемого к dll, написанной на C, а не моя придумка

предполагается что в RowData будет непрерывный кусок данных, с разной длиной.


MBo   (2007-02-02 13:13:00) [16]

> RowData: record end;
Что это?


Arm79   (2007-02-02 13:09:00) [17]

function ReadBytes(Data: PChar; Count: integer; var Position: integer): TByteArray;
 var
   i:integer;
begin
 SetLength(Result, Count);
 for i := 0 to Count-1
 do begin
   Result[i] := ReadByte(Data, Position);
 end;
end;


Сергей М.   (2007-02-02 13:05:00) [18]

А что, в теле ReadBytes() тоже GetMem() вызывается ?


Наверх

Титульная страница Поиск, карта сайта Написать письмо