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

Вниз

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

Наверх





Память: 0.52 MB
Время: 0.004 c
15-1386937096
Богдан80
2013-12-13 16:18
2014.06.29
Забанили в гугле


2-1377684212
Jimmy
2013-08-28 14:03
2014.06.29
Создание emf+ и png файла с помощью GDI+


15-1386856880
Ega23
2013-12-12 18:01
2014.06.29
Народ, а как в Excel-е добавить N рядов?


15-1386869684
alex2013
2013-12-12 21:34
2014.06.29
ищем опытного программиста...


15-1386793811
Юрий
2013-12-12 00:30
2014.06.29
С днем рождения ! 12 декабря 2013 четверг





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