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

Вниз

Странность при работе с Record   Найти похожие ветки 

 
solomon ©   (2012-01-09 11:52) [0]

Давно не работал с записями, а сейчас вот столкнулся и не могу понять в чем дело.

Есть струкрута:

type
 TProjectStructure = record
   ProjectName: string[255];
   ProjectMode: word;
   AccountsName: tstringlist;  
end;

Структура описана в специальном юните в котором я храню общие для всего проекта процедуры, функции и вот теперь решил поместить туда же такую вот структуру данных.

В одном из модулей в обработчике события клика на кнопке я описываю локальную переменную ProjectPosting:

var
ProjectPosting:TProjectStructure;
begin
 //заполняем ProjectPosting
 ProjectPosting .ProjectName:=trim(Edit1.text);

//состояние проекта
ProjectPosting .ProjectMode:=1; //active

//список аккаунтов
ProjectPosting .AccountsName:=tstringlist.Create;
for i:=0 to CheckListBox1.Items.Count-1 do
  if CheckListBox1.Checked[i] then ProjectPosting.AccountsName.Add(CheckListBox1.Items.Strings[i]);

//Сохраняем структуру данных в стрим
TasksStream.WriteBuffer(ProjectPosting,SizeOf(TProjectStructure));

Если не написать ProjectPosting .AccountsName:=tstringlist.Create;
то получаю AV, что собственно логично.

Далее в другой форме идет чтение данных в обработчике клика мыши:

Var
ProjectTweetsPosting:TPostingProjectStructure; //описываем локальную переменную

Begin
      TasksStream.ReadBuffer(ProjectPosting,SizeOf(TPostingProjectStructure));
….
      if ProjectTweetsPosting.ProjectMode=1 then
       begin          
        for k:=0 to ProjectTweetsPosting.AccountsName.Count-1 do
         accs.Add(ProjectTweetsPosting.AccountsName.Strings[k]);
       end;

Странность в следующем. В последней форме почему-то уже не требуется AccountsName:=tstringlist.Create. Как это понимать, ведь ProjectTweetsPosting это локальная переменная на нее не должны распространяться действия произведенные в другом модуле где я писал «ProjectPosting.AccountsName:=tstringlist.Create;» ?


 
Сергей М. ©   (2012-01-09 12:08) [1]


> это локальная переменная на нее не должны распространяться
> действия произведенные в другом модуле


Должны.
Процесс-то тот же самый, адресное пространство одно и то же.
Адрес объекта, единожды созданного при tstringlist.Create, записан в стрим и валиден при чтении из стрима, если в промежуток времени между записью и чтением объект не был уничтожен.


 
solomon ©   (2012-01-09 12:17) [2]

Так, ну хоть какая-то ясность. Значит фактический все равно я получаю глобальную переменную так чтоли?

Другими словами если в любом модуле моей программы я один раз опишу ProjectPosting:TPostingProjectStructure; и загружу в структуру данные, то после этого в любой другой форме, так же локально для нее описав ProjectPosting:TPostingProjectStructure я получу доступ к записанным ранее в данную структуру данным? Получается что-то вроде указателя, имена могут быть разные, а данные все равно хранятся только в одном месте...


 
Сергей М. ©   (2012-01-09 12:26) [3]


> фактический все равно я получаю глобальную переменную так
> чтоли?


Не глобальную переменную, а область памяти, выделенную в куче и имеющую сторого определенный адрес, доступный из любой точки программы.


 
solomon ©   (2012-01-09 12:35) [4]

Ок, пусть будет область памяти. Но фактически вести то себя все это дело будет как глобальная переменная. В одном месте программы записали данные, в другом их можно считать. Сергей, а как не отказывась от Record (уж очень он удобен для хранения разнородных данных и работы с TStream) реализовать разграничение адресных пространств так сказать ? Проблема в том, что в большой программе я наверняка гденибудь да забуду очистить за собой данные если они будут общими для всех и в итоге будут непонятные ошибки. Неужели придется в каждом модуле описывать один и тот же тип TProjectStructure = record ?


 
Сергей М. ©   (2012-01-09 13:06) [5]

А зачем вообще тебе стрим понадобился в ДАННОМ случае ?
Это довольно важно ..


 
sniknik ©   (2012-01-09 13:11) [6]

> Но фактически вести то себя все это дело будет как глобальная переменная.
нет, может и не повезти так что будет указывать на объект (перетрется другим), а может указатель будет указывать в другую область на код... после будешь "ловить" AV уже на нем, в совершенно не определенном месте, и иногда, ну вот звезды так сложились (условия)...

> я наверняка гденибудь да забуду
не забывай. создал - уничтожь как стало не нужным.
кстати тут, имхо, лучше не рекорд, а класс... конструктор, деструктор, все инкассировано, при освобождении общего внутренние ссылки на обьекты "нилятся" после освобождения. и все дела. никаких странностей не будет.
"сохранять в стрим" тоже можно по своему, можно вместе с данными внутреннго объекта, восстанавливать также. ну как и если требуется.


 
sniknik ©   (2012-01-09 13:14) [7]

> инкассировано
;) да уж, исправило ошибку... - инкапсулированно.


 
solomon ©   (2012-01-09 16:48) [8]

Да про класс уже подумал, это был бы выход. Вопрос сохранится ли он в стрим. Покопаю. На счет того зачем нужен стрим. В нем удобно хранить набор данных который в свою очередь состоить из разнородных данных - Record.


 
sniknik ©   (2012-01-09 18:04) [9]

> Вопрос сохранится ли он в стрим.
все в твоих руках... напиши метод отдающий данные для стрима/и принимающий оттуда.

> В нем удобно хранить набор данных который в свою очередь состоить из разнородных данных - Record.
удобно это как есть без изменений хранить объекты, а с преобразованиями это уже не удобно.


 
solomon ©   (2012-01-09 19:42) [10]

sniknik с классом пока не получается http://delphimaster.net/view/1-1326116288/. Если все же решу оставить работу с records, как лучше поступать? Описывать структуру как я делал раньше централизовано в одном месте не вариант. Может тогда для каждого модуля описывать эту структуру отдельно и тогда у каждо из низ будет свое адресное пространство и пересечься они не смогут?

Но во всем этом деле с записью и чтением в стрим меня волнует другой вопрос.

Как можно корректно выделить память через SizeOf для переменной AccountsName: tstringlist; ? Точнее при записи в стрим все понятно, сколько создали итемов в tstringlist столько они памяти и заняли. А как же происходит рассчет при чтении из стрима? Я же не сообщаю процедуре TasksStream.ReadBuffer сколько у меня ожидается элементов в переменной AccountsName, как же компилятор рассчитывает ее размер?


 
Сергей М. ©   (2012-01-09 20:27) [11]


> как же компилятор рассчитывает ее размер?


Очень просто: SizeOf(TStringList) = SizeOf(TObject) = SizeOf(Pointer) = 4 (для Win32)

> как же происходит рассчет при чтении из стрима?

Точно так же: резервируется 4 байта под указатель на местоположение в памяти объекта TStringList


 
sniknik ©   (2012-01-09 21:12) [12]

> как лучше поступать?
имхо, тебе сейчас лучше попытаться понять разницу между объектом и данными в нем...
вот зачем пытаешься сохранить в стрим объект? какой смысл? если он тебе нужен ну и "храни" его как есть объектом, если нужны данные то и сохраняй в стрим их.

и вообще НАФИГА тут стрим? только не говори удобно, это ничего не объясняет.
а то получается типа
- зачем вы храните ношеные носки в кастрюле?
- удобно!
- ??? а зачем?, суп же после может носками пахнуть!
- ... эээ, а вот кстати не поможете, как избавится от запаха?
- не храни их там, или объясни зачем. без "удобно". смысл.


 
solomon ©   (2012-01-09 22:18) [13]

Хранить нужно данные, объект хранить не нужно.

Что касается вопроса зачем стрим. Постараюсь пояснить. Есть основной поток программы. В нем создается стрим. В этот стрим добавляются Record`ы с разной структурой. После заполнения стрима программа начинаем работать. Запускаются потоки, каждый из которых, обращаясь через критическую секцию к стриму ищет в нем данные для себя. Найдя данные извлекаются и дальше в данном потоке обрабатываются, а в стрим возвращается метка того что данные были обработаны тогдато. Так происходит в цикле через заданные промежутки времени. Другими словами стрим представляет собой центральное хранилище данных типа Records, а каждый Records в свою очередь является хранилищем неких настроек необходимых потокам для работы.


 
Сергей М. ©   (2012-01-09 23:01) [14]


> solomon ©   (09.01.12 22:18) [13]



> Хранить нужно данные, объект хранить не нужно


Хранение объекта и есть хранение данных, которые объект инкапсулирует.


 
нонамэ   (2012-01-09 23:17) [15]


> Хранить нужно данные, объект хранить не нужно.

Ну да... шкаф можно выкинуть


 
sniknik ©   (2012-01-09 23:28) [16]

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


 
solomon ©   (2012-01-10 00:49) [17]

список объектов это что за зверь?

Вот скажем у меня есть 4 типа рекордов, у каждого свой набор полей:
TProjectStructure1 = record
TProjectStructure2 = record
TProjectStructure3 = record
TProjectStructure4 = record

Хранилище (в моем случае стрим) выглядит например следующим образом:
TProjectStructure3
TProjectStructure1
TProjectStructure2
TProjectStructure1
TProjectStructure3
TProjectStructure4

Это последовательность записи данных в стрим. Каждая структура (record) имеет свой размер, мы его знаем и может прочесть из стрима нужные данные вычислив смещение к нужной нам структуре.

Как видите в хранилище могут попадаться одинаковые объекты просто с разными данными внутри. И как всю эту кухню хранить ума не приложу? Может дадите небольшой код?


 
Плохиш ©   (2012-01-10 01:42) [18]

TObjectList может хранить любые объекты в любых количествах и вариациях.


 
Германн ©   (2012-01-10 01:57) [19]

А TList вообще может хранить всё. Надо только учебник прочитать, чтобы узнать что такое "список".


 
Плохиш ©   (2012-01-11 02:43) [20]


> Германн ©   (10.01.12 01:57) [19]

Как-будто не знаешь, для кого учебники писаны...



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

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

Наверх




Память: 0.53 MB
Время: 0.008 c
15-1386937387
Никифиров И.В.
2013-12-13 16:23
2014.06.29
Виджеты для смарт-тв Самсунг


2-1377774807
delphi.coder
2013-08-29 15:13
2014.06.29
работа с объктом TFieldDataLink


15-1386866320
Абориген
2013-12-12 20:38
2014.06.29
Назвать DupeString() по-другому?


2-1377746622
FIL-23
2013-08-29 07:23
2014.06.29
chart имя легенды на графике


2-1377191147
Дмитрий
2013-08-22 21:05
2014.06.29
обновление по дате изменения файла