Имя: Пароль:
1C
1С v8
Исчерпанная переменная цикла
,
0 romix
 
13.07.17
12:37
Неоднократно сталкиваюсь с ошибкой такого вида:

    Для Каждого Строка1 из Объект.Состав Цикл
        Сообщить(Строка1.Количество);
    КонецЦикла;    
    
    Для Каждого Строка2 из Объект.Состав Цикл
        Сообщить(Строка1.Количество);
    КонецЦикла;    

Вы сразу видите ошибку? Во втором цикле обращается не к той переменной (цикл исчерпан, цирк уехал, а состояние переменной осталось). Система 1С, к сожалению, не выдает ошибку. Вопрос - как бы изловить все такие ошибки, может, есть методика или обработка?
1 Ёпрст
 
13.07.17
12:39
(0) так ошибки нет ?
Есть кривые ручки.
В любом языке переменная хранит последнее значение цикла.
2 craxx
 
13.07.17
12:40
(0) так это и не ошибка, когда он из коллекции не может достать, остается в итераторе последний элемент, его-то и вываливает в следующем цикле
3 Господин ПЖ
 
13.07.17
12:40
(1) в нормальных языках итераторы живут в пределах цикла
4 Ёпрст
 
13.07.17
12:40
чо тут можно посоветовать ?
Пользуй уникальные имена или обнуляй переменные.
5 Ёпрст
 
13.07.17
12:40
(3) это в каком, например ?
6 Господин ПЖ
 
13.07.17
12:41
(5) в яве, в шарпее
7 Ёпрст
 
13.07.17
12:41
в паскале, с++ - будет тоже, что и в (0)
8 Ёпрст
 
13.07.17
12:41
(6) гонишь
9 Господин ПЖ
 
13.07.17
12:42
(8) рукалицо...
10 Господин ПЖ
 
13.07.17
12:44
>Вопрос - как бы изловить все такие ошибки, может, есть методика или обработка?

есть. вынуть руки с ж.пы и давать уникальные локальные понятные имена переменным в рамках процедуры/функции
11 Ёпрст
 
13.07.17
12:45
(9) :)
Хочешь сказать, что опосля такого цикла
for (int i = 1; i <= 10; i++) {}
переменная i на выходе будет неопределена ? :)
12 Господин ПЖ
 
13.07.17
12:46
(11) прикинь...
13 lodger
 
13.07.17
12:47
(10) еще, если мозга хватит не запутаться, можно использовать одни и те же итераторы в циклах одного уровня.
14 Господин ПЖ
 
13.07.17
12:48
(13) ага. и все это еще закатать в рекурсию
15 lodger
 
13.07.17
12:48
(11) (12) не заставляйте честной люд запускать gcc. дайте уже результат выполнения программы.
16 1dvd
 
13.07.17
12:49
рекурсофобия детектед
17 romix
 
13.07.17
12:49
(11) Надо не for, а for each (Для Каждого).
18 Naf2017
 
13.07.17
12:50
(12) это как итератор определить

вот так вот вполне живет:

int i = 0 ;
for (int i = 1; i <= 10; i++) {}
i = 100;
19 Ёпрст
 
13.07.17
12:51
(12) ну-ну..
20 Господин ПЖ
 
13.07.17
12:51
(18) это коню понятно. но обычно вменяемые люди так не делают
21 Вафель
 
13.07.17
12:52
(0) Это ты про статистический анализ уже говоришь.
Для 1с к сожалению ничего нет
22 Ёпрст
 
13.07.17
12:52
(18) ты не поверишь, и так, живёт тоже

for (int i = 1; i <= 10; i++) {}
writeln(i);
23 romix
 
13.07.17
12:52
(10) Ну вот там коллега и дал понятные имена.
Я везде использую одну и ту же переменную для итератора, если так делать для всех циклов (кроме многоуровневых), то сабжевая проблема не появляется.
24 Naf2017
 
13.07.17
12:52
(22) ошибка компиляции
25 romix
 
13.07.17
12:52
(22) См. (17).
26 Вафель
 
13.07.17
12:53
Надо написать коллективную челобитную в PVS, может они для 1с выпустят модуль
27 Господин ПЖ
 
13.07.17
12:53
(22) >ты не поверишь, и так, живёт тоже

не поверю. в шарпе жить не будет
28 Filin
 
13.07.17
12:54
(5) В JavaScript в ES-2015 придумали специальное объявление переменных "let" для ограничения области видимости блоком.
29 Naf2017
 
13.07.17
12:54
30 Вафель
 
13.07.17
12:54
(28) а разве var не ограничивал?
31 Вафель
 
13.07.17
12:55
(29) мне кажется пример был из другого языка
32 Господин ПЖ
 
13.07.17
12:55
(28) да везде уже прикрутили... чтобы ничего лишнего не болталось по коду. и сбор мусора по возможности начинался раньше
33 1dvd
 
13.07.17
12:56
(24) (29) а если заранее объявить, что в ней будет?
34 romix
 
13.07.17
12:57
(26) Можно в 1С написать челобитную, чтобы по исчерпании цикла Для Каждого итератор само-обнулялся. :-)
35 Вафель
 
13.07.17
12:57
кстати кто-то уже задумывался вопросом
http://catalog.mista.ru/public/527258/
36 Вафель
 
13.07.17
12:57
(34) язык очень крайне неохотно расширяют в 1с
37 Naf2017
 
13.07.17
12:57
(33) 11
38 Господин ПЖ
 
13.07.17
12:58
(34) проще ромикса запретить
39 Naf2017
 
13.07.17
12:59
(34) да блин с чего это?
цикл мог вообще завершиться по Прервать или по Перейти
наконец по Попытка/Исключение

с другой стороны такое поведение цикла может быть вполне оправданным
40 Господин ПЖ
 
13.07.17
12:59
>язык очень крайне неохотно расширяют в 1с

его по хорошему вычищать надо

убирать хвосты из объектной модели 7.7, унифицировать всё... это как-то тупо - иметь 2 (или даже 3 - я не помню) диалекта языка запросов в рамках одного фреймворка
41 orefkov
 
13.07.17
13:02
(11)
До какой-то версии стандарта переменная оставалась "после цикла", потом изменили. Но MS VC++ отставал в реализации этого.
(0)
В 1С все локальные переменные метода имеют одну область видимости - весь метод.
42 Лефмихалыч
 
13.07.17
13:04
(0) у меня нет такой проблемы.
Имена переменным надо давать осмысленные просто и всё.
43 1dvd
 
13.07.17
13:04
(42) +100500
44 Лефмихалыч
 
13.07.17
13:04
(18) так делают только мудаки ващета
45 Naf2017
 
13.07.17
13:06
Даже нашел кусок кода, где это поведение используется:


Остаток = ...
                МассивСтрок = ...            
                Для каждого Эл Из МассивСтрок Цикл
                    Если Остаток=0 Тогда
                        Прервать;                    
                    КонецЕсли;
..............................
                КонецЦикла;
                Если Остаток>0 и Эл<>Неопределено Тогда
...............
46 Вафель
 
13.07.17
13:06
(42) Ты гений разработки. Пишешь без ошибок всегда?
47 Господин ПЖ
 
13.07.17
13:06
да начнется священный срач!!!
48 Naf2017
 
13.07.17
13:07
(44) какая разница кто так делает - важно, что зависит от области видимости переменной
49 romix
 
13.07.17
13:07
(39) Исключения или Перейти, по-моему, не нужны 100 лет в обед.

После же прерывания цикла смотреть состояния итератора вроде никогда и не нужно - ну а если он без прерываний завершился, или ни разу не состоялся, то тогда чего.
50 Вафель
 
13.07.17
13:07
Зачем же в других языках какие то инструменты используют? да еще и платно?
дебилы просто
51 Naf2017
 
13.07.17
13:07
(49) смотри (45)
52 vde69
 
модератор
13.07.17
13:07
(1) в функциональных языках такой ошибки не может быть (если только циклы не вложеные)
53 ELEA26
 
13.07.17
13:09
(1) "В любом языке переменная хранит последнее значение цикла." - да нифига! Не в любом. В Delphi переменная хранит что попало (закономерность не знаю), но не последнее значение.
54 Вафель
 
13.07.17
13:09
(52) Каких-каких языках?
55 Ёпрст
 
13.07.17
13:09
(41) ясно, я слишком стар, для всего этого дерьма :))
56 Naf2017
 
13.07.17
13:10
(53) не ври!
57 Лефмихалыч
 
13.07.17
13:10
(46) без ошибок не бывает, но такой проблемы, как у автора, у меня нет. Раз в квартал может перепутаю переменные - не чаще
58 Вафель
 
13.07.17
13:10
(57) и копипаст принципиально не используешь?
59 romix
 
13.07.17
13:11
(42) Вот сабжевая проблема и возникает как раз, когда коллеги пытаются давать "осмысленные имена".

Там одно осмысленное, здесь другое не менее осмысленное - в результате - сабж, незаметная трудноуловимая ошибка.

Я считаю, что циклам самой внутренней вложенности надо давать одинаковые имена, по крайней мере, пока проблема сабжа в 1С есть.
60 Лефмихалыч
 
13.07.17
13:11
(53) это если, разве что, в цикле делать что попало с переменной, тогда - да. А, если без извращений, то хранится таки последнее значение
61 Господин ПЖ
 
13.07.17
13:11
копипасту надо отменить
62 romix
 
13.07.17
13:11
(53) А там вообще есть цикл Для Каждого?
63 Господин ПЖ
 
13.07.17
13:11
клавиатуру тоже
64 Господин ПЖ
 
13.07.17
13:12
код надо писать на планшете, каллиграфически. вкладывая душу
65 Лефмихалыч
 
13.07.17
13:12
(58) если копипастю чужой код, заворачиваю его в функцию. Ну и, когда кописпастю, не зажмуриваюсь, а наоборот смотрю внимательно, откуда копе, куда пасте, и что в результате получилось
66 Вафель
 
13.07.17
13:12
тут как бы более общая проблема копипаста, а не каких-то циклов
67 Живой Ископаемый
 
13.07.17
13:12
в Swift, Obj-C переменные определенные в цикле, или например в if - видны только внутри этих конструкций.
https://www.dropbox.com/s/c4sjh3n9cbbw2oz/Screenshot%202017-07-13%2013.12.25.png?dl=0
68 Вафель
 
13.07.17
13:13
(65) Тут как раз копипаст своего кода
69 Naf2017
 
13.07.17
13:13
70 Господин ПЖ
 
13.07.17
13:14
(64) + полууставом

преподобному общему модулю СерверЛогирование раб божий ТонкийКлиент челом бьет
71 ELEA26
 
13.07.17
13:16
(56) не вру!
(60) не один раз с этим долбался. увы.
Приходится делать так:
IDX:=-1;
For N:=0 to 65535 do
Begin
  If Buf[N] = X Then
    Begin
      IDX:=N;
      BREAK;
    End;
End;
И тут смотреть IDX, т.к. N будет хрен знает чем (в пределах типа)!
72 1dvd
 
13.07.17
13:16
(67) ты бы ещё какой-нидь брейнфак вспомнил
73 Naf2017
 
13.07.17
13:19
(71) скорее всего у тебя там тупо переполнение
74 ELEA26
 
13.07.17
13:21
(73) Где тут переполнение? У n:integer или у array[0..65535] или где?
Ааа.. Я понял - ты упертый. Ну Ок. Значит считай, что я не прав. Как обычно все остались при своем мнении.
75 lubitelxml
 
13.07.17
13:22
(0) бывает, но редко, да и быстро отладчиком ловится
76 mistеr
 
13.07.17
13:23
(0) >как бы изловить все такие ошибки, может, есть методика или обработка?

Методика, как изловить, называется статический анализ. Для 1С еще никто не заморочился, насколько мне известно.

Есть также методика, как не делать таких ошибок. Нормально структурировать код. Если два цикла делают что-то похожее - объединить их в один. Если разное - выделить в методы.
77 Лефмихалыч
 
13.07.17
13:24
(68) копипастить код - это вообще всегда плохо. Тем более свой. За дублирование кода в приличных местах неприлично ругают
78 mistеr
 
13.07.17
13:25
(59) >Вот сабжевая проблема и возникает как раз, когда коллеги пытаются давать "осмысленные имена"

Неправда, осмысленные имена хорошо различаются, в том числе и на глаз. Строка1 и Строка2 это бессмысленные имена.
79 mehfk
 
13.07.17
13:26
(71)
{$APPTYPE CONSOLE}
Var
  IDX:Integer;
  X:Integer;
  Buf:Array[0..$FFFF] Of Integer;
  N:Integer;
begin

  Buf[10] := 100500;
  X:=100500;

  IDX:=-1;
  For N:=0 to 65535 do
  Begin
    If Buf[N] = X Then
      Begin
        IDX:=N;
        BREAK;
      End;
  End;
  Writeln('IDX = ', IDX);
  Writeln('N = ', N);
end.

IDX = 10
N = 10
80 vde69
 
модератор
13.07.17
13:26
(54) в функциональных...


есть процедурные типа си, паскаль, а есть функциональные например лисп
81 Лефмихалыч
 
13.07.17
13:26
(59) говнокод порождает массу проблем. Что тут обсуждать?
82 Господин ПЖ
 
13.07.17
13:32
(78) это же ромикс
83 Живой Ископаемый
 
13.07.17
13:34
2(80)Э... а почему важно что в функциональных? Я думал это просто как компилятор обработает правила. А правила - как договорятся.
Obj-C - не функциональный, это объектное расширение С.
Swift - ну да, до какой-то степени функциональный...
84 vde69
 
модератор
13.07.17
13:41
(83) в функциональной процедуре каждый оператор по своей сути это функция, в том числе и оператор цикла... и видимость переменных идет с верху в глубь

то есть переменная описанная выше цикла видно внутри цикла, а любая переменная созданная внутри цикла за его пределами не видна, и после выполнения функции цикла должна быть разрушена а память очищена
85 romix
 
13.07.17
13:42
(81) Осмысленные имена в итераторах - это и есть говнокод.
86 romix
 
13.07.17
13:43
(77) У вас проблемы с копипастом из-за осмысленных имен. Обезличенные имена (итераторов цикла) не дают проблему копипаста.
87 Лефмихалыч
 
13.07.17
13:43
(85) я не смогу перекалибровать свою систему ценностей так, чтобы понять это твое утверждение.
88 vde69
 
модератор
13.07.17
13:44
(85) соглашусь... есть Венгерская нотация, конечно применять ее полностью в 1с смысла нет (так как типизации в 1с просто нет), но использовать например префикс "м" для описания местных переменных, или "Сч" для описания счетчика цикла - это хороший тон
89 Лефмихалыч
 
13.07.17
13:45
(86) угу, особенно во вложенных циклах.
90 Лефмихалыч
 
13.07.17
13:45
(86) и у меня-то как раз нет проблем с копипастом, как и самого копипаста
91 Живой Ископаемый
 
13.07.17
13:46
2(84) ну это да, там каждый блок {} - это по сути анонимная инлайн-функция. со своим скопом. Но например в свифте такая инлайн фукнция захватывает контекст внутри которого он определен. (значения переменных на момент вызова).
Надо проверить код на обж-Си. будет
92 vde69
 
модератор
13.07.17
13:46
(88) +

у меня все итераторы обозначены одинаково "эл", при вложенных циклах - добавляю номер вложености
93 romix
 
13.07.17
13:47
(87) У меня такое мнение сложилось, иначе ИМХО много проблем ниоткуда лезет в код. :)

(89) Вложенные циклы очень редки - но именно здесь нужны длинные осмысленные имена. (ИМХО).
94 romix
 
13.07.17
13:58
(92) Да, я тоже так делаю (для строк документа или таблицы - имена стр). Для вложенных циклов (которые редки) думаю удобнее полное имя в одном из случаев - чтобы имена резко контрастировали, да и для понятности.
95 romix
 
13.07.17
14:03
(45) А что будет с Эл, если вверху она где-то использовалась, а ни одна итерация цикла не состоялась?

Вне тела цикла по-моему смотреть на итератор все-таки опасно. :-) Тут напрашивается вынос тела ... эээ ... в функцию.
96 Naf2017
 
13.07.17
14:12
(95) вот поэтому оно вверху ни разу не использовалось, а если использовалось, то сделайте принудительно перед циклом:

Эл = Неопределено;
97 Господин ПЖ
 
13.07.17
14:59
(88) 1с против венгерской нотации
98 Господин ПЖ
 
13.07.17
14:59
а зря
99 romix
 
13.07.17
15:09
(96) Сегодня не использовалось, завтра коллеги добавят фрагмент-другой с этой же переменной, и внизу (может быть, далеко внизу) все сломается. Вы же в примере забыли сделать обнуление, и все с большой вероятностью тоже забудут (я, например, тоже забыл бы). Именно в этом примере может быть безопаснее проверять размер коллекции.
100 Лефмихалыч
 
13.07.17
15:11
(99) коллегам, которые так делают, не глядя, в древнем Риме отрывали пуп
101 Господин ПЖ
 
13.07.17
15:11
>Сегодня не использовалось, завтра коллеги добавят фрагмент-другой с этой же переменной, и внизу (может быть, далеко внизу) все сломается.

не нанимай на дело идиотов (с)
102 Сияющий Асинхраль
 
13.07.17
15:12
Такие ошибки как в (0) возникают в большинстве своем после копирования кусков кода :-) , пиши все сам и такой проблемы не будет :-)
103 Господин ПЖ
 
13.07.17
15:14
+ и что значит "далеко внизу".

что за спагетти-код?

вы с коллегами вместо того чтобы фольгой спутников шуршать книжку полистали типа "Совершенный код" Макконнелл и ИТС

пользы бы было в жизни больше
104 Кирпич
 
13.07.17
15:15
"как бы изловить все такие ошибки"
надо читать то, что пишешь. другого способа нет пока.
105 Господин ПЖ
 
13.07.17
15:16
способы есть, но не для 1с
106 Кирпич
 
13.07.17
15:17
(105) так про 1с вроде разговор
107 Сияющий Асинхраль
 
13.07.17
15:18
+(102) Да и ловятся такие ошибки на раз, что свои, что чужие, недельку назад потешался, когда как раз такую ошибку в одной из франчевых конфигураций выловил :-)
108 romix
 
13.07.17
15:19
(100) (101) Код же должен быть безопасным в этом отношении. Да и язык я бы тоже попытался сделать безопасным (автообнулять переменную цикла по его исчерпанию, объявление локальных переменных внутри блока).

(102) Другой способ - одинаковые переменные - итераторы цикла везде. А не двугорбых верблюдов плодить, думая, что это совершенный код. :-)

(104) Есть - я сейчас думаю автообнулять после цикла, если переменных итератора цикла внутри одной функции больше одной. Какие-то случаи использования вне цикла имхо опасны ошибками.
109 Господин ПЖ
 
13.07.17
15:19
>Да и ловятся такие ошибки на раз

они увы не всегда прозрачны. сам напарывался несколько раз на разные эффекты из-за кривой копипасты
110 Вафель
 
13.07.17
15:20
(107) каким способом?
111 Живой Ископаемый
 
13.07.17
15:21
короче, что мы тут мечтаем. Хотя бы в каком-то отношении синтаксис языка поменялся с момента выхода 8.0? (не говорю о новых фукнциях, именно синтаксис)
112 Naf2017
 
13.07.17
15:21
мне кажется у товарища romix какой-то ГСМ
113 Господин ПЖ
 
13.07.17
15:22
>Код же должен быть безопасным в этом отношении.

код увы никому ничего не должен.

а контора конкретно торчит теперь на 2,5 лимона из-за пограмиста в сандалетах и носочках
114 Кирпич
 
13.07.17
15:22
(108) эту ошибку должен транслятор отлавливать. А ты хоть обнуляй хоть не обнуляй ошибка останется
115 YFedor
 
13.07.17
15:23
Проблема в (0) только один из случаев невнимательности, вот еще один, причем тоже без ошибок:

Для Каждого Строка1 из Массив1 Цикл

        Сообщить(Строка1);

    Для Каждого Строка1 из Массив2 Цикл
            Сообщить(Строка1);
        КонецЦикла;  

КонецЦикла;  

тут тоже 1С виноват?


Что я хочу сказат? А то, что проблема в (0) далеко не самая насущная среди тех, что мешают жить
116 Naf2017
 
13.07.17
15:25
Да и так всем известно, что 1С-скрипт сваяли из гуана и палок

Ну так что ж теперь? Нам все равно с этим жить
117 Лефмихалыч
 
13.07.17
15:25
(108) >Да и язык я бы тоже попытался сделать безопасным
а вот из таких вот побуждений появляются всякие пидорские руби, в которых вэйп, гироскутер и подвёрнутые штаны называют выразительностью...
118 Живой Ископаемый
 
13.07.17
15:27
2(115) а зачем это стыдливое "1"? Почему не просто
Для Каждого Строка ИЗ?
119 YFedor
 
13.07.17
15:27
(118) потому же, почему и в (0)
120 romix
 
13.07.17
15:33
(115) Эээ тут бы тоже транслятору ругнуться на нехорошее...

(117) Изоляция переменных, объявленных внутри блока, автообнуление итератора цикла Для Каждого - по-моему, это незначительное улучшение - в крайнем случае, использовать переключатель в корне конфигурации. Если бы он был, я бы прямо сейчас его и включил. :-)
121 Вафель
 
13.07.17
15:35
(120) А что там нехорошего? Во вложенных циклах предлагаешь не давать доступ к данных внешних?
122 Вафель
 
13.07.17
15:36
(120) А зачем вообще 2 раза обходить тч?
123 romix
 
13.07.17
15:36
(121) Нехорошее - одинаковый итератор цикла в двух вложенных циклах.
124 romix
 
13.07.17
15:41
(122) Несколько тч. В каждой выполняете какие-то проверки или другие действия.
127 Живой Ископаемый
 
13.07.17
15:43
+(126) ага
129 Fish
 
13.07.17
15:46
А может, надо просто уметь программировать? :))
130 Господин ПЖ
 
13.07.17
15:47
(129) ты задаешь убийственный вопрос
131 Лефмихалыч
 
13.07.17
15:56
(129)
132 Fish
 
13.07.17
15:58
(130) Я, помнится, когда только осваивал программирование на Си (году где-то в 89-м), назвал файлик с текстом проги "prn". При попытке его скомпилировать получал совершенно неожиданные ошибки какждый раз в разных местах. Весь отдел собрался и полчаса не могли найти, в чём же ошибка :))

С тех пор я бережно отношусь к именам переменных и проч, уже на автомате.
133 Живой Ископаемый
 
13.07.17
16:32
2(132) а как ты этого добился? В винде нельзя создать файлик с таким именем. а также con, aux
134 Живой Ископаемый
 
13.07.17
16:36
135 Лефмихалыч
 
13.07.17
16:37
(133) та легко!
https://i.imgur.com/3iWf9mO.png
136 Лефмихалыч
 
13.07.17
16:38
+(135) гЫ! prn проводником удалился, а con  - не хочет :))
137 Fish
 
13.07.17
16:40
(133) Это не в винде было, а в ДОСе, и редактор МультиЭдит (емнип) с лёгкостью такой файлик записал и открывал тоже нормально. Но вот попытка его скомпилировать приводила к неожиданным результатам.