Массив структур

  • Автор темы Автор темы f87
  • Дата начала Дата начала
F

f87

Нужно было добится хранения по типу "Параметр - Значение" в массиве.
Пример реализации типа Record (Pascal) в массиве. Но, значения передаются в массив по ссылке (!), что значительно усложняло задачу...

[codebox]структ = новый Структура("знач1, знач2");
структ.знач1 = 110;
структ.знач2 = 120;
массив[0] = структ;

структ.знач1 = 510;
структ.знач2 = 520;
массив[1] = структ;[/codebox]

В Итоге получется что массив[0].знач1 = 510 !!!. Все элементы массива ссылаются на одну переменную.
Проблема была решены следующим образом...

[codebox]Процедура ИмпортДопСправочников() Экспорт
мас = новый массив();
ПолучитьСтруктуруДопСправочника(мас);

Для каждого П Из мас Цикл
Сообщить(П.Название);
Сообщить(П.КодПоля);
КонецЦикла;

КонецПроцедуры

Функция ПолучитьСтруктуруДопСправочника(Буффер)
дПоля = Новый XBase(БазаДанныхMagistr + "POLE.DBF", БазаДанныхMagistr + "POLE.CDX", Истина);

Пока дПоля.Следующая() Цикл
Буффер.Добавить(Новый Структура("Название, КодПоля", дПоля.POLE_NAZV, дПоля.POLE_KODP));
КонецЦикла;

Возврат Истина;
КонецФункции[/codebox]

Как ни сиранно, но обект структуры не уничтожился после завершения работы функции. И теперь доступен из другой процедуры.
А вот теперь вопрос! Как долго будут "жить" объекты структуры в массиве? Когда 1С уничтожает объекты?
Хочу услашать ваши мнения, критику и альтернативные решения. Спасибо за внимание.
 
Не уверен, что понял вопрос
Попытаюсь прояснить (может и ответить)
На сколько я знаю, 1С (по крайней мере 7.7) всегда передает в процедуры сам объект, а не ссылку
Соответственно, после вызова ПолучитьСтруктуруДопСправочника(мас); все данные записанные в мас будут доступны везде, где он объявлен, независимо от типа этой переменной

В принципе, это должно также работать в любом языке
По крайней мере будет верно для C++

А проблема кода
Код:
структ = новый Структура("знач1, знач2");
структ.знач1 = 110;
структ.знач2 = 120;
массив[0] = структ;
структ.знач1 = 510;
структ.знач2 = 520;
массив[1] = структ;
в том, что массив[0] хранит ссылку на объект, который затем изменяется
надо либо хранить объект, либо создавать новый объект каждый раз пред сохранением ссылки в очередной элемент массива
 
Я с Вами полностью согласен - либо создавать новый объект каждый раз. Но вот нюанс - Время "жизни" переменной/объекта (Не глобальной) ограничевается функцией (В моём случае объект "структура") - покрайней мере так написанно во всех справочниках. Т.е. создал в функции, а пользоватся надо в другой процедуре. Если предположить что в выражении массив[0] = структ; производится именно копирование структуры, а сам структ в дальнейшем уничтожится то проблема решается сама собой.
Но в выражении массив[0] = структ; производится передачи ссылки на объект (Это уже проверенный вариант!) А это значит что, после завершения функции ПолучитьСтруктуруДопСправочника 1С может в любой момент сама уничтожить объект структ. Тогда я потеряю значения всех элементов массива!
Я перефразирую свой вопрос: Когда 1с уничтожает отработанные объекты?
 
Я перефразирую свой ответ :)

Я могу и ошибаться, но на 99% уверен, что 1С тоже уничтожает объекты по завершении функции
Но когда выполняется Буффер.Добавить(Новый Структура("Название, КодПоля", дПоля.POLE_NAZV, дПоля.POLE_KODP)), то в Буффер попадает не ссылка, а копия объекта и сия копия не будет уничтожена пока будет жить сам Буффер
В вашем конкретном примере - это везде где объявлен мас

Хотя, как я понял, ваш пример из 1С 8, с которой я не работал и лучше проверить на примере
В любом случае, я уверен, что 1С не уничтожает объекты в произвольный момент, и главное - это убедится, что вы храните копию объекта, а не ссылку на него


На сколько я знаю, 1С (по крайней мере 7.7) всегда передает в процедуры сам объект, а не ссылку

Я тут намудрил, точнее говоря неверно использовал термины
Правильнее сказать, что 1С передает именно ссылку (а можно передать только значение, если на это указать) и при изменении переменной внутри процедуры или функции затем будет доступно ее новое значение
 
Я провёл эксперимен ...

[codebox]МояСтруктура = Новый Структура("Знач1, Знач2", 0, 0);

* * *

МояСтруктура.Знач1 = 111;
МояСтруктура.Знач2 = 111;
Буффер.Добавить(МояСтруктура);
МояСтруктура.Знач1 = 222;
МояСтруктура.Знач2 = 222;
Буффер.Добавить(МояСтруктура);
МояСтруктура.Знач1 = 333;
МояСтруктура.Знач2 = 333;
Буффер.Добавить(МояСтруктура)

* * *

// Другая процедура

Для каждого Элемент из Буффер цикл
Сообщить(Элемент.Знач2);
КонецЦикла;[/codebox]

В результате получаю след

333
333
333


Это говорит о том, что м буффере хранится именно Ссылка на объект! Следовательно если добавлять елемент Новый структура() то в Буффере будут так же хранится ссылки! А то, что они доступны после завершения функции говорит о том, что объект не уничтожен (по крайней мере сразу). На Pascal такой фокус 100% не прокатит. В общем меня интересует как скопировать объект или узнать: кто, когда, и зачем его удалит.

Повторюсь. Может кто предложит своё решение.
 
Действительно загадочно
с одной стороны можно изменить на

Код:
Буффер.Добавить(Новый Структура("Знач1, Знач2",111,111));
Буффер.Добавить(Новый Структура("Знач1, Знач2",222,222));
Буффер.Добавить(Новый Структура("Знач1, Знач2",333,333));
// Другая процедура
Для каждого Элемент из Буффер цикл
Сообщить(Элемент.Знач2);
КонецЦикла;

И наверняка получится
111
222
333


А с другой, действительно непонятно сколько будут храниться объекты ссылки на которые записаны в Буффер
И лично я согласен, что это не вполне корректная ситуация

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

Только тогда непонятно, почему сразу не создавать копии, а хранить именно ссылки

f87, если не сложно (мне уже стало интересно) после вывода значений в цикле запишите в один из Элементов новое значение и выведите снова: измениться во всех или только в одном?
 
Извеняюсь за долгое молчание. Продолжим... :)
вот код по вашей просьбе:
[codebox]
Мас = новый массив();
МояСтруктурра = новый Структура("Знач1", "Знач1_Эл1");
Мас.Добавить(МояСтруктурра);

МояСтруктурра.Знач1 = "Знач1_Эл2";
Мас.Добавить(МояСтруктурра);

МояСтруктурра.Знач1 = "Знач1_Эл3";
Мас.Добавить(МояСтруктурра);

Для каждого Эл Из Мас Цикл
Сообщить("Вывод № 1 " + строка(Эл.Знач1));
КонецЦикла;

Мас[1].Знач1 = "Изменённое_Значение";

Для каждого Эл Из Мас Цикл
Сообщить("Вывод № 2 " + строка(Эл.Знач1));
КонецЦикла;
[/codebox]

Вот результат:

Вывод № 1 Знач1_Эл3
Вывод № 1 Знач1_Эл3
Вывод № 1 Знач1_Эл3
Вывод № 2 Изменённое_Значение
Вывод № 2 Изменённое_Значение
Вывод № 2 Изменённое_Значение

;) Я сам в шоке. Я вот думаю, может объекты в 1С "живут" по принципу DLL в виндовозе? Если нет ссылок то уничтожаются (но тогда любой объект может быть глобальным!)? Вообщем нужно знать на верняка. Может задать вопрос разработчикам?
 
из моего опыта следует что пока есть ссылки на объекты (что в семерке, что в восьмерке) объект не уничтожается. но есть одна тонкость: в семерке проверка на ссылки и уничтожение объектов происходит при закрытии формы для модуля формы. а для модуля документа - по окончании процедуры Обработка проведения (а точнее по окончании транзакции).
 
Как показывает практика, объекты уничтожаются далеко не всегда. Допустим, ТЗ получаемая при выгрузке результатов запросов зачастую остаются висеть в памяти (при том что ссылок на нее, естественно, не существует). Насколько я знаю, для гарантированной очистки памяти при использовании запроса 1с рекомендует воспрользоваться таким объектом как "МенеджерВременныхТаблиц", хотя и старый добрый метод пЗапрос = 0 еще никто не отменял.

PS: А зачем вообще понадобилась подобная конструкция с массивом структур. Мне кажется, двумерный массив или ТаблицаЗначений вполне вас спасет...
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!