• 15 апреля стартует «Курс «SQL-injection Master» ©» от команды The Codeby

    За 3 месяца вы пройдете путь от начальных навыков работы с SQL-запросами к базам данных до продвинутых техник. Научитесь находить уязвимости связанные с базами данных, и внедрять произвольный SQL-код в уязвимые приложения.

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

    Запись на курс до 25 апреля. Получить промодоступ ...

Странный баг

  • Автор темы Истребитель
  • Дата начала
И

Истребитель

Добрый день.

Есть код внешенй обработки, который при помощи com объекта обращается из базы данных (приёмник) 1С 8.1 в другую базу данных (источник) 1С 8.1 .
Считывает из неё список документов (конкретных, счета на оплату покупателя) и что-то с ними делает и пишет в текущую базу.

Источник находится на 1С 8.1 СЕРВЕРНОЙ
Приёмник находился на 1С 8.1 ФАЙЛОВОЙ

В коде существует место, где аттрибут документа, полученного из ком объекта, передаётся в функцию

То есть:
Док - это ссылка на документ, полученный через Com объект представляющий собой базу на севрере 1С 8.1

Есть функция:
Код:
Функция Тест (Строка1)
Если Строка1="" Тогда
Строка1="Значение_По_Умолчанию";
КонецЕсли;
...
Возврат Найденное_Значение;
КонецФункции
Дальше вызывается функция от аттрибута документа:
Код:
НайденныйСклад = Тест(Док.Склад.Наименование);
Так вот, пока база Приёмник была ФАЙЛОВАЯ, всё работало нормально!

Перенесли базу Приёмник на СЕРВЕР. Перенос путём создания новой пустой базы и загрузки базы из файла dt. После этого то место в коде, где переданному параметру присваивается значение, стало выдавать ошибку!

Ошибка при установке значения атрибута контекста Строка1 Метод не найден

Посмотрел код - тип значения Строка1 - строка. Обычная такая строка. Однако ошибка. Какого хрена? И почему она появилась после переноса кода на сервер?

Сделал так, что убирает ошибку:
Код:
Функция Тест (Строка2)
Строка1=Строка2;
Если Строка1="" Тогда
Строка1="Значение_По_Умолчанию";
КонецЕсли;
...
Возврат Найденное_Значение;
КонецФункции
Внимание вопрос(Ы)!

1) Правильно ли я сделал, что так убрал эту ошибку? Не утопил ли я крысу в колодце, так что она затем сгниёт и всё умрёт от чумы?
2) Почему вообще возникает эта ошибка?
3) Почему она возникла только после перехода на сервеную базу?
4) Почему добавление одного присваивания исправляет ошибку?

И финальный вопрос:

Правильно ли я понимаю, что оператор = присваивает значение, а не ссылку, всегда, то есть:

Код:
Х="А";
У=Х;
Х="Б"
У будет равно по прежнему "А"
Но в функцию передаётся ссылка? То есть:

Код:
Функция Ф(Х)
Х="Б";
КонецФункции;

Х="А"
Ф(Х);
Х будет равно "Б"

Но тогда почему раньше эта ошибка не вылазила?
И вылезла только после переноса?

Поясните плиз...
 
Д

Дайнеко

Ой!
Ф-ии дали на входе параметр типа ссылка: Тест(Док.Склад); Где Склад ну явно не строка а справочник "Склады".
Не понимаю я вот чего:
- Почему ее сравнивают с строкой ?
- Дальше еще веселее: ей присваивают строку! Это все равно что написать Док.Склад="Значение_По_Умолчанию";
- "Посмотрел код - тип значения Строка1 - строка. Обычная такая строка." Вот действительно Какого ....? Если должен быть справочник.
 
И

Истребитель

Склад там это строка!
Правда строка.
Я проверял через "вычислить значение". Док.Склад это свойства объекта Док и оно типа строка.

UPD: Ошибся, Док.Склад это и правда не строка, в функцию же передаётся его наименование, т.е. Док.Склад.Наименование
 
Д

Дайнеко

Ошибка - результат корявого программирования. Ф-ии дали параметр. Нормальная ф-ия должна взять его, что-то вычислить и вернуть свой результат, при этом не изменяя входные параметры.
Зачем в ней надо было:
Если Строка1="" Тогда
Строка1="Значение_По_Умолчанию";
КонецЕсли;
Т.е. мимоходом "портим" входной параметр.
В возврате-то все равно какая-то переменная "Найденное_Значение".
Была цель изменить "Док.Склад" в "Значение_По_Умолчанию" ?

Что касается "Я проверял через "вычислить значение"" - не верю. Если "Док" это объект в базе, открытой через COM, то навряд отладчик покажет красиво его тип, наверно показывает его представление. Лучше не гадать, а откройте конфигуратор базы-источника и покажите кусок описания структуры. А я приготовлюсь уши отрывать.
 
И

Истребитель

1) Код не мой, поэтому не могу сказать какова была изначальная цель
2) Код 100% работал 100% без вылетов на этом месте, то есть когда база, в которой обработка открывалась, была файловой, присваивание строки в этот аттрибут РАБОТАЛО КОРРЕКТНО
3) При переходе на клиент-серверную базу, открытие и запуск обработки стал выдвать вот эту ошибку.

Таким образом, независимо от того, какого типа какой объект в каком конфигураторе, вопрос в другом - почему на клиент серверной базе ошибка, а на файловой её нет?

Однако прошу прощения, я вас дезинформировал.
Передается не склад, а его наименование - Док.Склад.Наименование
Склад действительно имеет тип справочник.склады в оригинальной базе.
 
Д

Дайнеко

А че голову ломать? Код некорректный - значит надо править. И что с того, что раньше работал. Разве что на душе более тоскливо.
 
H

Hryv

Ошибка - результат корявого программирования. Ф-ии дали параметр. Нормальная ф-ия должна взять его, что-то вычислить и вернуть свой результат, при этом не изменяя входные параметры.
:lool:

с чего вы это взяли?
в нормальных языках, типа С++, есть четкое разделение понятий значение и ссылка
в общем случае можно умышленно использовать конструкции типа
Код:
Функция Ф(Х)
Х="Б";
КонецФункции;

Х="А"
Ф(Х);
Х будет равно "Б"


другое дело, что в 1С, где практически все явное неявно, а неявное явно лично я уже рефлекторно избегаю присвоения значений в сомнительных или неоднозначных ситуациях
и не только я
в 1С 7.7 широко распространено, например: а=СокрЛП(б);


честно, я не знаю как 1С 8 все это обрабатывает и даже не удивлен, что на файлах и сервере работает поразному
Истребитель, думаю, что ваше решение вполне приемлимо
Код:
Функция Тест (Строка2)
Строка1=Строка2;
Если Строка1="" Тогда
Строка1="Значение_По_Умолчанию";
КонецЕсли;
...
Возврат Найденное_Значение;
КонецФункции

Добавлено: Кстати говоря в том же 1С полно случаев передачи контекста в процедуру или функцию, где этот контекст потом вдоль и поперек подвергается изменениям
 
Д

Дайнеко

Да! Я против того, чтобы Ф-ия меняла входные параметры.
Код:
 Так будет почти правильно (зачем вообще переприсваивать?):
Функция Тест (Строка2)
Строка1=Строка2;

Он же приводит пример:
Код:
Функция Тест (Строка1)
Строка1="Значение_По_Умолчанию";
Возврат ДругаяПеременная;

Внимательно на названия переменных посмотрите. Здесь же изменяется входной параметр. Я говорю не столько о работоспособности, сколько о стиле, который и является залогом надежности.

А еще одним из элементов хорошего стиля является внятное название переменных. От цифирек глаза рябит.
В общем, я бы за такой код руки оторвал.
 
U

unknown181538

Что-то про Синтаксис-Помощник не вспомнили:

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

т.е. можно писать Функция МояФункция(Знач Параметр
получается, что раньше неправильно работало? Честно говоря, не верю ;)
 
V

vbs

А еще одним из элементов хорошего стиля является внятное название переменных.
В порядке флуда.
Работал я много лет назад с одним классным программистом.
Вот он писал примерно так (код был на Паскале, поэтому привожу русский аналог) :

Процедура ЗакрытьВспомогательныеТаблицыИОставитьПрограммуРезидентной(СписокПереданныхПарам
етров,СписокЗакрываемыхТаблиц)

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

unknown181538

Слишком длинные тоже не очень люблю (ПроцессорВыводаДанныхСистемыКомпановкиВТабличныйДокументИмениНуралиеваБорисаГео
ргиевича).
Плохо читается, когда много подобных переменных.
 
V

vbs

Ну, согласен, лучше покороче. Но у описываемого мастера это были в основном названия процедур.
Понятно, что счетчики цикла и прочую лабуду он не заморачивался именовать информативно
 
U

unknown181538

Сегодня правил обработку с глобальными переменными:
"перем дз, дт, динд, табт, табк;

Процедура НачатьД()
динд=1;
дз=Новый XBase; "
Хотелось совершить какое-нибудь членовредительство в отношении автора, чтобы больше не писал.
 
V

vbs

Да ясно, какой. На 8-ю букву называется.
 
Мы в соцсетях:

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