Страницы

Последствия возврата значения через неявную ссылку

В Active Oberon в процедурах-функциях доступна локальная переменная RESULT. Она представляет собой ссылку на переменную, в которую возвращают значение. Это сделано для возможности экономить ресурсы при возврате структур (массивов, записей и указателей на них), но такое решение хранит в себе подвох.

Если актуальный параметр совпадает с переменной, принимающей значение, есть риск пересечения ссылок, что может привести к ошибочному результату[0].

MODULE Reverse; IMPORT Out;

 TYPE Arr = ARRAY 3 OF INTEGER;
 
 PROCEDURE DoSurprize*(CONST a: Arr): Arr;
 VAR i: INTEGER;
 BEGIN
  FOR i := 0 TO LEN(a) - 1 DO
    RESULT[i] := a[LEN(a) - i - 1]
  END;
 RETURN RESULT
 END DoSurprize;

 PROCEDURE Do*        (CONST a: Arr): Arr;
 VAR i: INTEGER; RESUIT: Arr;
 BEGIN
  FOR i := 0 TO LEN(a) - 1 DO
    RESUIT[i] := a[LEN(a) - i - 1]
  END;
 RETURN RESUIT
 END Do;

 PROCEDURE Test*;
  PROCEDURE Go(reverse: PROCEDURE(CONST a: Arr): Arr);
  VAR i: INTEGER; a, b: Arr;
  BEGIN
    FOR i := 0 TO LEN(a) - 1 DO a[i] := i END;
    b := reverse(a);
    FOR i := 0 TO LEN(b) - 1 DO Out.Int(b[i], 4) END; Out.Ln;
    b := reverse(b);
    FOR i := 0 TO LEN(b) - 1 DO Out.Int(b[i], 4) END; Out.Ln; Out.Ln
  END Go;
 BEGIN
  Go(Do);
  Go(DoSurprize)
 END Test;

END Reverse.

Что приводит к результату:

   2   1   0
   0   1   2

   2   1   0
   0   1   0

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

MODULE Reverse2; IMPORT Out;

 TYPE Arr = ARRAY 4 OF INTEGER;
 
 PROCEDURE Do*(): Arr;
 VAR i, t: INTEGER;
 BEGIN
  FOR i := LEN(RESULT) DIV 2 TO 1 BY -1 DO
    t := RESULT[i - 1];
    RESULT[i - 1] := RESULT[LEN(RESULT) - i];
    RESULT[LEN(RESULT) - i] := t
  END;
 RETURN RESULT
 END Do;

 PROCEDURE Test*; VAR i: INTEGER; a: Arr;
 BEGIN
  a := INTEGER([0, 1, 2, 3]);
  a := Do();
  FOR i := 0 TO LEN(a) - 1 DO Out.Int(a[i], 4) END; Out.Ln
 END Test;

END Reverse2.
   3   2   1   0

Примечания

[0] О выявлении пересечений параметров в Oberon читайте в заметке

Комментариев нет:

Отправить комментарий