Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2003.05.29;
Скачать: [xml.tar.bz2];

Вниз

Пара вопросов про 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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.51 MB
Время: 0.008 c
7-95135
kva
2003-03-31 13:07
2003.05.29
Не работает MessageBeep


1-94797
Apachi
2003-05-19 09:12
2003.05.29
Запись и чтение ресурса


14-95020
Ruslan
2003-05-12 05:50
2003.05.29
Саоздание АмперМетра


3-94776
dpv
2003-05-12 12:28
2003.05.29
работа в консоле


14-95032
Pat
2003-05-08 16:21
2003.05.29
Выключение Win2k





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