Не могу разобраться с указателем.
От: Uglion  
Дата: 10.07.12 04:08
Оценка:
Есть вот такая запись:


  PSurface = ^TSurface;

  TSurface = record
    Left: word;
    Top: word;
    Width: word;
    Height: word;
    Depth: byte;
    Ident: word;
    Data: IDirectDrawSurface7;
  end;




В Чём разница:

вариант 1.


var
 TempSurf:TSurface;

begin
 TempSurf.Data:=nil;         //этот вариант работает, но мне он не интересен.
end;




вариант 2.


var
 TempSurf:PSurface;

begin
 GetMem(TempSurf,sizeof(TSurface));
 TempSurf^.Data:=nil         //тут выдаёт ошибку
end;
Re: Не могу разобраться с указателем.
От: BlackEric http://black-eric.lj.ru
Дата: 10.07.12 07:26
Оценка:
Здравствуйте, Uglion, Вы писали:

U>Есть вот такая запись:


U>
U>var
U> TempSurf:PSurface;

U>begin
U> GetMem(TempSurf,sizeof(TSurface));
U> TempSurf^.Data:=nil         //тут выдаёт ошибку
U>end;
U>


Ну и какую же ошибку он выдает?
https://github.com/BlackEric001
Re: Не могу разобраться с указателем.
От: Jack128  
Дата: 10.07.12 07:47
Оценка:
Здравствуйте, Uglion, Вы писали:

U>вариант 2.



U>
U>var
U> TempSurf:PSurface;

U>begin
U> GetMem(TempSurf,sizeof(TSurface));
U> TempSurf^.Data:=nil         //тут выдаёт ошибку
U>end;
U>


используй New(TempSurf) вместо GetMem

GetMem отдает сырую, неинициализированную память, а для работы с интерфейсами/строками/дин массивами/вариантами память должна быть инициализирована. Вобщем заведи привычку под типизированные указатели выделять память через New, а освобождать через Dispose
Re[2]: Не могу разобраться с указателем.
От: BlackEric http://black-eric.lj.ru
Дата: 10.07.12 07:55
Оценка:
Здравствуйте, Jack128, Вы писали:

U>>
U>>var
U>> TempSurf:PSurface;

U>>begin
U>> GetMem(TempSurf,sizeof(TSurface));
U>> TempSurf^.Data:=nil         //тут выдаёт ошибку
U>>end;
U>>


J>используй New(TempSurf) вместо GetMem


J>GetMem отдает сырую, неинициализированную память, а для работы с интерфейсами/строками/дин массивами/вариантами память должна быть инициализирована. Вобщем заведи привычку под типизированные указатели выделять память через New, а освобождать через Dispose


Или можно
 GetMem(TempSurf,sizeof(TSurface));
 FillChar(TempSurf^,sizeof(TSurface), 0);
https://github.com/BlackEric001
Re: Не могу разобраться с указателем.
От: icWasya  
Дата: 10.07.12 08:20
Оценка: 9 (1)
Здравствуйте, Uglion, Вы писали:

U>Есть вот такая запись:



U>
U>  PSurface = ^TSurface;

U>  TSurface = record
U>    Left: word;
U>    Top: word;
U>    Width: word;
U>    Height: word;
U>    Depth: byte;
U>    Ident: word;
U>    Data: IDirectDrawSurface7;
U>  end;
U>




U>В Чём разница:


U>вариант 1.... работает, потому что Data в этом случае и так равна Nil

U>вариант 2.... Не работает потому что Data в этом случае заполнена мусором

А любое присвоение переменной типа интерфейс

  Surface.Data := NewValue;

превращается в

  if Surface.Data<>Nil then Surface.Data._Release();
  Surface.Data := NewValue;
  if Surface.Data<>Nil then Surface.Data._AddRef();


Кроме того, если сради локальных переменных ( или полей
структур локальных переменных) процедуры есть интерфейсного типа,
то Delphi оборачивает тело процедуры примерно в такой код


var
  Surface : TSurface;
begin
  Surface.Data:=Nil;                      //<<--
  try                                     //<<--
   (* 
     всё 
     что 
     вы 
     напишете 
     сами
   *)
  finally                                 //<<-- 
    if Surface.Data<>Nil then             //<<--
       Surface.Data._Release();           //<<--
  end;                                    //<<--
end;

При выделении памяти через New, тоже добавляется код,
отвечающий за инициализацию таких полей, поскольку есть ссылка на тип.

А GetMem только выделяет память и никак её не инициализирует.

Также смотреть в сторону Initialize/Finalize.
Re: Не могу разобраться с указателем.
От: Аноним  
Дата: 10.07.12 08:40
Оценка:
Здравствуйте, Uglion, Вы писали:

U>
U>var
U> TempSurf:PSurface;

U>begin
U> GetMem(TempSurf,sizeof(TSurface));
U> TempSurf^.Data:=nil         //тут выдаёт ошибку
U>end;
U>


Либо используй AllocMem, либо сам чисти выделенный блок FillChar(TempSuff^, SizeOf(TSurface)). После чего TempSuft^.Data := NIL делать, разумеется, не нужно.
Re[3]: Не могу разобраться с указателем.
От: Аноним  
Дата: 18.07.12 14:18
Оценка:
Здравствуйте, BlackEric, Вы писали:

BE>Или можно

BE>
BE> GetMem(TempSurf,sizeof(TSurface));
BE> FillChar(TempSurf^,sizeof(TSurface), 0);
BE>


Эт чтобы не использовать AllocMem ? :-D
Re[4]: Не могу разобраться с указателем.
От: BlackEric http://black-eric.lj.ru
Дата: 18.07.12 15:12
Оценка:
Здравствуйте, http://the-arioch.livejournal.com/, Вы писали:

HTA>Здравствуйте, BlackEric, Вы писали:


BE>>Или можно

BE>>
BE>> GetMem(TempSurf,sizeof(TSurface));
BE>> FillChar(TempSurf^,sizeof(TSurface), 0);
BE>>


HTA>Эт чтобы не использовать AllocMem ? :-D


From SysUtils:
function AllocMem(Size: Cardinal): Pointer;
begin
  GetMem(Result, Size);
  FillChar(Result^, Size, 0);
end;


Я не знал про неё
https://github.com/BlackEric001
Re[5]: Не могу разобраться с указателем.
От: Аноним  
Дата: 18.07.12 18:27
Оценка:
HTA>>Эт чтобы не использовать AllocMem ? :-D
BE>Я не знал про неё

А она в какому-то смысле основная.

Вроде как интерфейс менеджера памяти, который в Delphi как известно меняется когда надо, состоит из 4 функций.
Если не путаю. AllocMem, ReAllocMem, FreeMem, и GetMemBlockSize кажется
Re[6]: Не могу разобраться с указателем.
От: BlackEric http://black-eric.lj.ru
Дата: 18.07.12 18:39
Оценка:
Здравствуйте, http://the_arioch.livejournal.com/, Вы писали:


HTA>>>Эт чтобы не использовать AllocMem ? :-D

BE>>Я не знал про неё

HTL>А она в какому-то смысле основная.


HTL>Вроде как интерфейс менеджера памяти, который в Delphi как известно меняется когда надо, состоит из 4 функций.

HTL>Если не путаю. AllocMem, ReAllocMem, FreeMem, и GetMemBlockSize кажется

Это смотря в какой версии.
В Delphi 7 нет.

В XE2 она выглядит совсем по другому и находится уже в System.

от менеджера памяти зависит GetMemory

function GetMemory(Size: NativeInt): Pointer; cdecl;
begin
  Result := MemoryManager.GetMem(Size);
end;
https://github.com/BlackEric001
Re: Не могу разобраться с указателем.
От: lgb Канада  
Дата: 18.07.12 20:05
Оценка:
Здравствуйте, Uglion, Вы писали:

var
 pTempSurf:PSurface;

begin
 New(pTempSurf);                               // создали, заняли память
 FillChar(pTempSurf^, SizeOf(pTempSurf^), 0);  // обнулили поля структуры (опционально)

 TempSurf^.Data := nil;                        // пользуемся...

 Dispose(pTempSurf);                           // попользовались, освободили память
end;


Сто лет на Дельфи не писал, но должно быть как-то так.
Re[7]: Не могу разобраться с указателем.
От: Аноним  
Дата: 19.07.12 10:06
Оценка:
BE>Это смотря в какой версии.
BE>В Delphi 7 нет.

Вот блин, а в Delphi 5 менялось...
Я ж тогда 2KB DLL делал, без выбивания стандартного heap'а этого бы не получилось.

А в D6 до сих пор втыкается FastMM4 — http://fastmm.svn.sourceforge.net/viewvc/fastmm/FastMM4_Readme.txt?revision=62&amp;view=markup

Вообще предлагаю простоe правило — как только появились borlandmm.dll и midas.dll — не позже этого стали и переключаемый heap manager. возможно раньше.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.