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

Вниз

Пара вопросов про ObjectPascal   Найти похожие ветки 

 
Maksim Realov   (2003-05-16 18:39) [0]

Здравствуйте! Хотел спросить про структуры и ссылки на них.
Если я объявляю структуру так:

type
TMyStruct = record
i: integer;
s: string;
end;

а потом использую её в таком виде:

procedure TForm1.Button1Click(Sender.TObject);
var
MyStruct: TMyStruct;
begin
MyStruct.i:= 5;
end;

То при таком способе объявления переменной MyStuct память под неё резервируется при запуске приложения и освобождается по его закрытии. Так?
А если я объявляю так:

type
PMyStruct = ^TMyStruct;
TMyStruct = record
i: integer;
s: string;
end;

procedure TForm1.Button1Click(Sender.TObject);
var
MyStruct: PMyStruct;
begin
New(MyStruct);
MyStruct^.i:= 5;
Dispose(MyStruct);
end;

То при таком способе определения память выделяется и освобождается динамически.
Но ведь MyStruct объявленная как TMyStruct тоже является фактически завуалированным указателем на туже структуру.
Ведь если сделать так:

type
TMyStruct = record
i: integer;
s: string;
end;

procedure TForm1.Button1Click(Sender.TObject);
var
M1, M2: TMyStruct;
begin
M1.i:= 5;
M2.i:= 7;
end;

В таком случае М1 и М2 ссылаются на разные экземпляры структур. И под эти две переменные распределяется автоматически память.

Мои рассуждения верны?

И ещё вопрос – почему после уничтожения объекта (метод Free) ссылка на него не обнуляется?


 
Романов Р.В. ©   (2003-05-16 18:51) [1]


> procedure TForm1.Button1Click(Sender.TObject);
> var
> MyStruct: TMyStruct;
> begin
> MyStruct.i:= 5;
> end;

Переменная MyStruct локальная по этому память под нее (грубо говоря) выделяется только при выполнении этой процедуры и после выхода из нее освобождается.


> И ещё вопрос – почему после уничтожения объекта (метод Free)
> ссылка на него не обнуляется?

На объект может быть куча сслок. Их все нужно обнулять? Используй FreeAndNil для обнуления ссылки и освобождения памяти


 
Юрий Федоров ©   (2003-05-16 18:52) [2]

>procedure TForm1.Button1Click(Sender.TObject);
>var
> MyStruct: TMyStruct;
>begin
> MyStruct.i:= 5;
>end;

>То при таком способе объявления переменной MyStuct память под >неё резервируется при запуске приложения и освобождается по его >закрытии. Так?

Память резервируется при входе в процедуру, и освобождается при выходе из нее

>>Но ведь MyStruct объявленная как TMyStruct тоже является >>фактически завуалированным указателем на туже структуру.
MyStruct НЕ является указателем

>>И ещё вопрос – почему после уничтожения объекта (метод Free) >>ссылка на него не обнуляется?
Потому что объект ничего не знает о ссылке на него, ссылок кстати может быть несколько




 
Skier ©   (2003-05-16 18:52) [3]

>Maksim Realov

1)
procedure TForm1.Button1Click(Sender.TObject);
var
MyStruct: TMyStruct;
begin
MyStruct.i:= 5;
end;

-Память под переменную MyStruct (8 байт) выделяется при входе
в процедуру(метод)
-Освобождается при выходе из процедуры(метода)
- Всё делает компилятор, тебе не надо здесь заботится о памяти

2)
procedure TForm1.Button1Click(Sender.TObject);
var
MyStruct: PMyStruct;
begin
New(MyStruct);
MyStruct^.i:= 5;
Dispose(MyStruct);
end;

- MyStruct это указатель на запись (4 байта)
- память под MyStruct (4 байта) выделяется при входе
в процедуру(метод) и освобожнается при выходе.
- память же под то на что собственно указавает MyStruct тебе
нужно выделять и освобождать самому.

3)

> И ещё вопрос – почему после уничтожения объекта (метод Free)
> ссылка на него не обнуляется?


Освобождается память которую занимает экземпляр класса, ссылка
на него это всего лишь типизированный указатель (4 байта) ( "похожий" на MyStruct: PMyStruct;) )
Если нужно обнулять и ссылку, то используй FreeAndNil(...)


 
Юрий Федоров ©   (2003-05-16 18:52) [4]

Не успел :-)


 
MBo ©   (2003-05-16 18:53) [5]

1)Под локальные переменные память выделяется в стеке при входе в процедуру и освобождается при выходе.
2) Начиная с D5 появилась процедура FreeAndNil.
Можно и руками обNil-ять.
А не сделано авт. обнуление, поскольку ссылок на объект может быть несколько в разных местах, и автоматически все их обнулить нельзя.


 
MBo ©   (2003-05-16 18:54) [6]

;))


 
Serginio   (2003-05-16 19:01) [7]

Пусть войдет в привычку
New(MyStruct); FillChar(MyStruct^,SizeOf(TMyStruct),0);
// или Pointer(MyStruct.s):=nil;
MyStruct^.i:= 5;//
//MyStruct.i:= 5; без разницы
MyStruct.s:="xxxxxxxxxxx";// можешь получить инвалид поинтер операцию если не обнулишь структуру



 
Skier ©   (2003-05-16 19:05) [8]


> MyStruct.s:="xxxxxxxxxxx";// можешь получить инвалид поинтер
> операцию если не обнулишь

Это...вряд ли. (С) тов. Сухов


 
Maksim Realov   (2003-05-16 19:15) [9]

так зачем же тогда вообще заморачиваться с указателями на структуру, если можно просто:

MyStr: TMyStr;

и всё???
Зачем вводить PMyStr = ^TMyStr ???


 
Skier ©   (2003-05-16 19:18) [10]

>Maksim Realov (16.05.03 19:15)
А затем, что при выходе из метода у тебя у же не будет
MyStr, а сие не всегда нужно, задачи-то разные бывают...


 
Maksim Realov   (2003-05-16 19:22) [11]

Тогда я вообще не понимаю в чём разница использования MyStr: TMyStr; и MyStr: PMyStr; кроме незначительной разницы в распределеии и освобождении памяти (в первом случае это делает компилятор, во втором - программер)???



 
Serginio   (2003-05-16 19:24) [12]

>>Skier © (16.05.03 19:05)
При New структура не инициируется нулями и на месте s будет не nil компилятор при виде такого безобразия попробует удалить данную строку за не нужность. Если не веришь мне вот борландовский код TstringList
procedure TStringList.InsertItem(Index: Integer; const S: string; AObject: TObject);
begin
Changing;
if FCount = FCapacity then Grow;
if Index < FCount then
System.Move(FList^[Index], FList^[Index + 1],
(FCount - Index) * SizeOf(TStringItem));
with FList^[Index] do
begin
Pointer(FString) := nil;
FObject := AObject;
FString := S;
end;
Inc(FCount);
Changed;
end;


 
Skier ©   (2003-05-16 19:27) [13]

>Maksim Realov (16.05.03 19:22)

> кроме незначительной разницы в распределеии и освобождении
> памяти

В контексте твоего вопроса эта разница не незначительной,
а огромна !

И я так понимаю, что ты ещё ни разу не использовал с своих
проектах дин. структур и работу с ними, поэтому, (из-за того что
тебе не понятна область применения) ты не улавливаешь всей
разницы.


 
Serginio   (2003-05-16 19:35) [14]

>>>Maksim Realov (16.05.03 19:22)
Обязательно найди книжечку Вирта про связные спискы. А также при работе с не сртруктурированной памятью распределенной память
Для проимера у тебя есть ссылка на кусок памяти p:Pchar;
If PInteger(p)=3 Then
inc(p,sizeOf(Integer);
If PMyStruct(p).i=5 Then
А вообще можно миллион примеров привести, особенно работая с АПИ где все передается по указателям.
Например при вызове процедуры типа
Procedure (Var t:TMyStruct); аналогична
Procedure (t:PMyStruct) в С применяется больше такой подход.


 
Maksim Realov   (2003-05-16 19:35) [15]

>> Skier © (16.05.03 19:27):

Вот я и хочу уловить разницу, что бы делать всё правильно и осмысленно!


 
Maksim Realov   (2003-05-16 19:38) [16]

Вы меня извините ребята за тупость, но понять не могу: при t:TMyStruct в переменной t лежит указатель на экземпляр структуры!

Книги я читаю конечно и читать буду - без этого никуда!


 
Skier ©   (2003-05-16 19:40) [17]

>Serginio (16.05.03 19:24)

for ii := 0 to 100000 do begin
New(MyStruct);
MyStruct^.s := "Hello, world !";
Dispose(MyStruct);
end; //for

AV получишь хоть раз ?


 
Serginio   (2003-05-16 19:51) [18]

Все может быть значит повезло но, New не инициализирут память 0.
И поверь мне натыкался не раз.


 
Serginio   (2003-05-16 20:00) [19]

>>Maksim Realov
Нет при выделении памяти под Т компилятор запоминает ее адрес сам. При динамическом выделении памяти в куче ответственность за адресс структуры лежит на прогрммисте. Можно запомнить адрес структуры например
t:TMyStruct;
Pt,pt2:PMyStruct ;
PT:=@t;
pt.i:=5;// t=5;
new(pt2);
pt:=pt2;
pt.i:=3;// pt2^3;

и работать со структурой по указателю. Это особенно важно когда не знаешь где эта переменная находится в стеке или в куче.


 
Serginio   (2003-05-16 20:14) [20]

Skier © (16.05.03 19:40)
Кстати скорее всего я не прав New инициализирует структуру, а Dispose уничтожает все правильно. Все мои посты относятся к GetMem и другим типам не структурированного выделения памяти.Честно говоря уже и не помню когда работал с New и Dispose.


 
Skier ©   (2003-05-16 20:20) [21]

>Serginio (16.05.03 20:14)

> New инициализирует структуру, а Dispose уничтожает все правильно

Совершенно правильно.


 
Serginio   (2003-05-16 20:40) [22]

Еще раз извиняюсь за свое невежество (Вернее память). Был не прав. В основном пользуюсь хипами, что очень удобно при одновременном уничтожении памяти, а вместо всякого рода листов динамические массивы лучше всего.


 
Skier ©   (2003-05-16 20:45) [23]

>Serginio (16.05.03 20:40)
Nobody"s perfect. :)


 
Maksim Realov   (2003-05-20 10:42) [24]

Так что лучше использовать для выделения памяти под структуру: New/Dispose или GetMem/FreeMem?

А если не выделить память под структуру и попытаться произвести запись в её поля, то всегда будет AV?


 
Skier ©   (2003-05-20 10:45) [25]

>Maksim Realov (20.05.03 10:42)
1)Для твоего случая New/Dispose
2)Трудно сказать всегда или нет, может разок другой повезёт,
но это совершенно не значит что под динамические
структуры не надо выделять память.


 
Digitman ©   (2003-05-20 11:10) [26]


> если не выделить память под структуру и попытаться произвести
> запись в её поля, то всегда будет AV?


нет, не всегда.
связано это с выравниванием блоков аллокируемой памяти на границу, специфичную для конкретного менеджера памяти, а так же со странично-ориентированным управлением вирт.памятью на уровне ОС

скажем, запросил ты у менеджера памяти 1 байт

var
MyArray: PChar;
..
GetMem(MyArray, 1);

и теперь обращаешься к памяти явно за пределами массива

MyArray[3] := #0; // исключения в случае с менеджером от Борланда никогда не возникнет !

MyArray[15] := #0; // исключения в случае с менеджером от MS в (составе, например, MSVCRT) никогда не возникнет !

MyArray[4] := #0; // вероятность исключения в случае с менеджером от Борланда существует ! все зависит от того, как "ляжет" страница)





Страницы: 1 вся ветка

Текущий архив: 2003.05.29;
Скачать: CL | DM;

Наверх




Память: 0.54 MB
Время: 0.018 c
7-95134
Che
2003-03-31 13:29
2003.05.29
Backspace и Delit


9-94653
паша2
2002-12-17 13:12
2003.05.29
проверка столкновений


4-95161
caesar
2003-04-02 10:58
2003.05.29
SystemTray


1-94938
Лесник
2003-05-17 22:55
2003.05.29
Самый старый файл в папке


1-94822
Novichok_
2003-05-19 13:23
2003.05.29
Как мне передать значение переменной из одной формы в др.