OberonCore
https://forum.oberoncore.ru/

Особенность WITH - предупреждение при компиляции
https://forum.oberoncore.ru/viewtopic.php?f=2&t=3959
Страница 1 из 2

Автор:  Info21 [ Воскресенье, 06 Май, 2012 09:58 ]
Заголовок сообщения:  Особенность WITH - предупреждение при компиляции

Иван Денисов писал(а):
Добавил предупреждение при опасной компиляции, спасибо ilovb!
Пож., суммируйте суть в двух словах, раз уж Вы продрались сквозь альтернативные истерики.

(модератор) выделено: viewtopic.php?p=72568#p72568

Автор:  Иван Денисов [ Воскресенье, 06 Май, 2012 11:52 ]
Заголовок сообщения:  Re: Красноярская сборка BlackBox 1.6rc6

Info21 писал(а):
Пож., суммируйте суть в двух словах, раз уж Вы продрались сквозь альтернативные истерики.
Если создать расширяемый тип и два потомка, то в секции WITH, отвечающей за обработку конкретного потомка переменной, невозможно присвоить этой переменной указатель на другого потомка, что очень правильно, так как может привести к ошибке, мы ведь в этой секции только с первым потомком собирались работать! Обычно, компилятор выдает ошибку и отказывается собирать программу. Кроме случая который нашел ilovb. Если в WITH передавать указатель через переменный аргумент отдельной функции. В этом случае компиляция происходит, но работа приложения приводит к ошибке работы с памятью. Блек бокс в конвульсиях умирает (самый страшный случай пока из которых я видел :) ... поэтому считаю резонным выдавать предупреждение, но лучше конечно, чтобы тоже запрещалась компиляция. Но я пока не умею работать с маркерами ошибок и т.п.

Вот накидал для разъяснения несколько модифицированный пример ilovb
Код:
MODULE Test2;
   IMPORT Out;

   TYPE
      R0 = POINTER TO  EXTENSIBLE RECORD END;
      R1 = POINTER TO RECORD (R0) a: ARRAY 100 OF CHAR END;
      R2 = POINTER TO RECORD (R0) END;

   VAR
      globalPointer: R0;
      r1: R1;
      r2: R2;

   PROCEDURE Print (x: R0);
   BEGIN
      IF x IS R1 THEN Out.String("R1"); Out.Ln
      ELSIF x IS R2 THEN Out.String("R2"); Out.Ln END
   END Print;

   PROCEDURE Yes*;
   BEGIN
      NEW(r1);
      globalPointer :=  r1;
      
      WITH globalPointer: R1 DO
         Print(globalPointer);
         NEW(r2);
         (* globalPointer := r2;  такую операцию собрать невозможно, выдается ошибка *)
         Print(globalPointer); globalPointer.a := "jsdfdfkjghdfkdfghkjdffhgkjdhfgkjhdfkjghdfk";
      END
   END Yes;

   PROCEDURE Not (VAR localPointer: R0);
   BEGIN
      WITH localPointer: R1 DO
         Print(localPointer);
         NEW(r2);
         globalPointer := r2; (* А такую собрать можно, и будет ошибка работы с памятью *)
         Print(localPointer); localPointer.a := "jsdfdfkjghdfkdfghkjdffhgkjdhfgkjhdfkjghdfk";
      END
   END Not;
   
   PROCEDURE CrashTest*;
   BEGIN
      NEW(r1);
      globalPointer :=  r1;
      Not(globalPointer);
   END CrashTest;

BEGIN
END Test2.

^Q Test2.CrashTest

Автор:  ilovb [ Воскресенье, 06 Май, 2012 12:04 ]
Заголовок сообщения:  Re: Красноярская сборка BlackBox 1.6rc6

Иван Денисов писал(а):
...Кроме случая который нашел ilovb...

Чтобы исключить недоразумения и ради справедливости хочу сказать следующее:
На сколько я знаю эту ошибку когда-то обнаружил trurl.
Сергей Губанов привел пример кода, когда эта ошибка возникает. А я уже немного модифицировал его, чтобы показать к чему это может привести.

Ошибку в компиляторе, из-за которой не выводилось предупреждение обнаружил Kemet

Автор:  Info21 [ Воскресенье, 06 Май, 2012 15:18 ]
Заголовок сообщения:  Re: Красноярская сборка BlackBox 1.6rc6

Ох уж этот Trurl...

Он, вроде, давным-давно эти ошибки указал (там была ещё одна как минимум; даже кажется в своих лекциях об этом рассказывал).

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

Конечно, лучше, чтобы их не было.
С другой стороны, влазить в компилятор -- и фактически вносить поправочки в определение старого ядра языка -- тоже чревато.
Мало ли.
Кому надо, есть исходники.

Автор:  QWERTYProgrammer [ Воскресенье, 06 Май, 2012 17:05 ]
Заголовок сообщения:  Re: Красноярская сборка BlackBox 1.6rc6

Указанная Трурлем ошибка, о которой я помню: Как испортить память, не используя SYSTEM, никакого отношения к WITH не имела. Может кто-то еще помнит, где обсуждались проблемы с WITH?

Автор:  Евгений Темиргалеев [ Воскресенье, 06 Май, 2012 22:07 ]
Заголовок сообщения:  Re: Красноярская сборка BlackBox 1.6rc6

Вы не про это?
Peter Almazov писал(а):
Вы почитайте диссертацию Шиперски, там есть вещи и похуже. Например, в операторе WITH есть дефект. Там не гарантируется сохранность указателя, у которого уже определили тип, внутри тела WITH. Стр. 210:
Код:
TYPE
  P = POINTER TO R;   
  R = RECORD END;   
  P1= POINTER TO R1;   
  R1 = RECORD (R) x: INTEGER END;   
PROCEDURE F;   
  VAR p:P; p1:P1;   
  PROCEDURE G;   
  BEGIN NEW(p) END G;   
BEGIN NEW(p1);p:=p1;   
  WITH p: P1 DO   
    p.x:=0;  (*legal, since p has been   guarded to P1 *)
    G;       (*this destroys the assertion of the WITH guard*)   
    p.x := 42 (*havoc!!*)   
  END   
END F;

P.S. В Обероне-07 WITH убран.

Автор:  Peter Almazov [ Воскресенье, 06 Май, 2012 22:14 ]
Заголовок сообщения:  Re: Красноярская сборка BlackBox 1.6rc6

Евгений Темиргалеев писал(а):
Вы не про это?
Peter Almazov писал(а):
Из архива достать изволили?
Так может и удалять не надо было?

(модератор) Нарушение п. 2.2. правил. Временная блокировка на 1 сут.

Автор:  Info21 [ Понедельник, 07 Май, 2012 05:39 ]
Заголовок сообщения:  Re: Красноярская сборка BlackBox 1.6rc6

Peter Almazov писал(а):
Вы почитайте диссертацию Шиперски
Питер, мои комплименты.
Уважаю которые первоисточники читают.

Автор:  Пётр Кушнир [ Понедельник, 07 Май, 2012 10:33 ]
Заголовок сообщения:  Re: Красноярская сборка BlackBox 1.6rc6

Евгений Темиргалеев писал(а):
P.S. В Обероне-07 WITH убран.

а в реализации GPCP внутри WITH поля записи становятся read-only

Автор:  Kemet [ Понедельник, 07 Май, 2012 13:28 ]
Заголовок сообщения:  Re: Красноярская сборка BlackBox 1.6rc6

ilovb писал(а):
Иван Денисов писал(а):
Ошибку в компиляторе, из-за которой не выводилось предупреждение обнаружил Kemet

Это не ошибка - с учетом того, что данный код тянется с древнего OberonV4 ( а может еще раньше), в котором, однако, при компиляции подобно кода, честно сообщаеся о возможных проблемах, а в ББ это сообщение скрывается, а значит и СОЗНАТЕЛЬНО скрывается наличие уязвимости.
А западенцы-потребители так любят судитья по любому поводу...

В то-же время это проблема конкретной реализации WITH, а не языка. Дыра не в WITH, а в голове у того, кто пишет такой дефективный код.

Автор:  Роман М. [ Понедельник, 07 Май, 2012 15:12 ]
Заголовок сообщения:  Re: Красноярская сборка BlackBox 1.6rc6

Kemet писал(а):
В то-же время это проблема конкретной реализации WITH, а не языка. Дыра не в WITH, а в голове у того, кто пишет такой дефективный код.
Поэтому возникает вопрос: почему ББ оберегает программиста от его ошибок (не даёт выстрелить себе в ногу или голову), а в некоторых случаях таки нет? Чем этот случай уникален с точки зрения разработчиков ББ?

Автор:  Info21 [ Понедельник, 07 Май, 2012 16:09 ]
Заголовок сообщения:  Re: Красноярская сборка BlackBox 1.6rc6

Надо бы этот диспут в отдельную тему.
Или опять начнётца латратус?

Автор:  Иван Денисов [ Понедельник, 07 Май, 2012 16:28 ]
Заголовок сообщения:  Re: Красноярская сборка BlackBox 1.6rc6

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

Автор:  QWERTYProgrammer [ Среда, 09 Май, 2012 21:37 ]
Заголовок сообщения:  Re: Красноярская сборка BlackBox 1.6rc6

Евгений Темиргалеев писал(а):
Вы не про это?

Именно про это, спасибо!

Автор:  QWERTYProgrammer [ Среда, 09 Май, 2012 22:28 ]
Заголовок сообщения:  Re: Особенность WITH - предупреждение при компиляции

На самом деле пример из диссертации Шиперски не приводит к крэшу в ББ: если бы G создавала пойнтер типа P, то да присваивание p.x := 42 обрушило бы ББ. Но внутри WITH G на самом деле создает пойнтер типа P1 и присваивание работает без проблем. Правда после выхода из WITH поле p.x становится недоступным. Что происходит с p.x непонятно: либо после выхода из WITH соотв. память освобождается, либо происходит утечка памяти. Вполне возможно, что проблема порчи памяти в этом примере действительно существовала в предыдущих версиях Оберона, но похоже, что в ББ авторы постарались ее по крайней мере обезвредить.

Автор:  Info21 [ Среда, 09 Май, 2012 23:36 ]
Заголовок сообщения:  Re: Особенность WITH - предупреждение при компиляции

Давайте уж и конструктивный ответ сообразим:

Пусть VAR t: POINTER TO Type;
и у Type есть расширения Type1 ...
и есть VAR t1: Type1 ...

Возникнет ли проблема в такой конструкции:

IF t IS Type1 THEN
t1 := t(Type1);
(* работаем с t1; подмена ссылки t не меняет ссылки t1 *)
ELSIF t IS Type2 THEN
t2 := t(Type2);
...

Автор:  Евгений Темиргалеев [ Четверг, 10 Май, 2012 07:24 ]
Заголовок сообщения:  Re: Особенность WITH - предупреждение при компиляции

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

Автор:  Info21 [ Четверг, 10 Май, 2012 08:24 ]
Заголовок сообщения:  Re: Особенность WITH - предупреждение при компиляции

Евгений Темиргалеев писал(а):
Info21 писал(а):
Давайте уж и конструктивный ответ сообразим:
На мой взгляд, Вирт решил проблему исключением WITH, потому, что между им и этой конструкцией ни в исходном ни в результирующем коде разницы почти нет. А язык с компилятором заодно несколько упрощаются.
Это понятно.

Мне важно убедиться, что приведённая конструкция решает задачу (я сейчас сильно вне контекста, поэтому боюсь промахнуться в какой-нибудь детали).

------
В итоге рекомендация: просто не использовать WITH.

------
И мораль: WITH -- пример поспешной оптимизации.
В экстазе творчества, видя, как здорово получается, потеряли бдительность и пропустили этого симпатичного, как оказалось, таракана :)

------
Можно ещё добавить, что WITH вылазит, видимо, крайне редко.
И не характерен для стиля, когда ООП интерпретируется как специфический способ расслоения функциональности между модулями в настоящих модульных системах.

Ставлю ссылку на Смысл ООП, и туда сейчас пару слов тоже.

Автор:  Info21 [ Пятница, 11 Май, 2012 21:55 ]
Заголовок сообщения:  Re: Особенность WITH - предупреждение при компиляции

Бессодержательный офтоп Kemet'а вместе с реакциями на него был удален по моей просьбе.

Уже были и Флейм, и Опять двадцать пять, и в тысяча двадцать пятый раз разводить латратус на темы вокруг да около никакого смысла нет.

Автор:  QWERTYProgrammer [ Суббота, 12 Май, 2012 01:12 ]
Заголовок сообщения:  Re: Особенность WITH - предупреждение при компиляции

Info21 писал(а):
В итоге рекомендация: просто не использовать WITH.

Кстати у Шиперски первым шло предложение запретить использовать WITH только с указателями.

Страница 1 из 2 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/