OberonCore

Библиотека  Wiki  Форум  BlackBox  Компоненты  Проекты
Текущее время: Среда, 20 Август, 2025 14:22

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 45 ]  На страницу Пред.  1, 2, 3  След.
Автор Сообщение
СообщениеДобавлено: Среда, 31 Октябрь, 2007 19:12 
Аватара пользователя

Зарегистрирован: Пятница, 25 Ноябрь, 2005 18:55
Сообщения: 2272
Откуда: Россия, Нижний Новгород
AVC писал(а):
мне удалось воспроизвести ошибку.

А мне опять не удалось воспроизвести.

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


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Среда, 31 Октябрь, 2007 20:34 
Аватара пользователя

Зарегистрирован: Суббота, 19 Ноябрь, 2005 15:59
Сообщения: 803
Откуда: Зеленоград
Сергей Губанов писал(а):
AVC писал(а):
мне удалось воспроизвести ошибку.

А мне опять не удалось воспроизвести.

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

Для верности надо отводить память в цикле.
Вот примерный код (конечно, ужасный, но это просто эксперимент):

Код:
MODULE VeryBad;

   IMPORT S := SYSTEM, Log, M := Services;

   CONST size = 10000000;
   TYPE
      Ptr = POINTER TO Rec;
      Rec = RECORD
         prefix: RECORD x, y, z: REAL END;
         v: ARRAY size OF INTEGER
      END;
   VAR p, q: Ptr;
      nfins: INTEGER;
   
   PROCEDURE (p: Ptr) FINALIZE-;
   BEGIN
      INC(nfins);
      Log.String("Finalize! "); Log.IntForm(S.VAL(INTEGER, p), 16, 8, '0', FALSE);
      Log.Int(p.v[0]); Log.Ln
   END FINALIZE;

   PROCEDURE Test* ;
      VAR p: Ptr;
      
      PROCEDURE PrintPtr(p: Ptr);
      BEGIN
         Log.String("p = ");
         Log.IntForm(S.VAL(INTEGER, p), 16, 8, '0', FALSE); Log.Ln;
      END PrintPtr;
      
      PROCEDURE Bad(VAR a: INTEGER);
         VAR i: INTEGER;
      BEGIN
         nfins := 0;
         REPEAT
            NEW(p); (* GC will be called here *)
            PrintPtr(p);
            IF (S.VAL(INTEGER, p) <= S.ADR(a)) & (S.ADR(a) < S.VAL(INTEGER, p) + SIZE(Rec)) THEN
               Log.String("Попался!!!"); Log.Ln;
               a := 10;
               FOR i := 0 TO LEN(p.v)-1 DO
                  IF p.v[i] = 10 THEN
                     Log.String("p[");
                     Log.Int(i);
                     Log.String("] =");
                     Log.Int(p.v[i]); Log.Ln
                  END;
                  RETURN;
               END;
               RETURN;
            END;
            a := 10;
         UNTIL (p.v[10] = 10) OR (nfins >= 200);
      END Bad;
   BEGIN
      NEW(p);
      PrintPtr(p);
      Bad(p.v[0]);
   END Test;

END VeryBad.

(!) VeryBad.Test


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Среда, 31 Октябрь, 2007 23:20 
Аватара пользователя

Зарегистрирован: Пятница, 25 Ноябрь, 2005 18:55
Сообщения: 2272
Откуда: Россия, Нижний Новгород
AVC писал(а):
...Вот примерный код...

Я его "усовершенствовал", срабатывает мгновенно:
Код:
MODULE TestCrash;

   IMPORT Log;

   PROCEDURE Do*; (* (!)TestCrash.Do *)
      VAR
         p: POINTER TO RECORD
            prefix: ARRAY 1000000 OF BYTE;
            v: ARRAY 1 OF BOOLEAN;
         END;

      PROCEDURE Crash (VAR x: BOOLEAN);
      BEGIN
         REPEAT
            NEW(p);
            x := TRUE
         UNTIL p.v[0];
         Log.String("Crashed!!!"); Log.Ln
      END Crash;
   
   BEGIN
      NEW(p);
      Crash(p.v[0])
   END Do;

END TestCrash.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Среда, 31 Октябрь, 2007 23:44 
Аватара пользователя

Зарегистрирован: Суббота, 19 Ноябрь, 2005 15:59
Сообщения: 803
Откуда: Зеленоград
Сергей Губанов писал(а):
AVC писал(а):
...Вот примерный код...

Я его "усовершенствовал", срабатывает мгновенно

Здорово! Суть как на ладони.
Мне кажется, что в таком виде это готовый bug report для OMAG.

Интересный момент.
Когда запускаешь TestCrash.Do сразу после загрузки BB, то действительно срабатывает мгновенно.
А я запустил после исполнения своего грубого наброска (т.е. в том же процессе, в котором искал до того способ воспроизвести ошибку), так TestCrash.Do работал до ошибки не меньше пары минут (видно, так куча уже была "измучена").


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Среда, 31 Октябрь, 2007 23:59 
Аватара пользователя

Зарегистрирован: Пятница, 25 Ноябрь, 2005 18:55
Сообщения: 2272
Откуда: Россия, Нижний Новгород
Вот так ещё проще:
Код:
MODULE TestCrash;

   IMPORT Log;

   PROCEDURE Do*; (* TestCrash.Do *)
      VAR a: POINTER TO ARRAY 100000 OF BOOLEAN;

      PROCEDURE Crash (VAR b: BOOLEAN);
      BEGIN
         REPEAT
            NEW(a);
            b := TRUE
         UNTIL a[0]
      END Crash;
   
   BEGIN
      NEW(a);
      Crash(a[0]);
      Log.String("Crashed!!!"); Log.Ln
   END Do;

END TestCrash.

Принципиально то, что переменная a объявлена внутри процедуры. Когда она глобальная вроде всё нормально.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 01 Ноябрь, 2007 09:31 

Зарегистрирован: Понедельник, 28 Ноябрь, 2005 10:28
Сообщения: 1440
Сергей Губанов писал(а):
Принципиально то, что переменная a объявлена внутри процедуры. Когда она глобальная вроде всё нормально.

Точно.
Код:
PROCEDURE Do*;
VAR p,q : POINTER TO ARRAY 10 OF CHAR;
   PROCEDURE Foo(VAR x: CHAR);
   BEGIN
     p := NIL;
     Kernel.Collect;
     NEW(q);  q^:='abcdefgh';
     x:='!';
   END Foo;
BEGIN
   Kernel.Collect;
   NEW(p);
   Foo(p[2]);
   Log.String(q); Log.Ln
END Do;


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 01 Ноябрь, 2007 20:18 

Зарегистрирован: Среда, 01 Август, 2007 00:13
Сообщения: 166
Есть ещё один способ "уронить" программу - с помощью прямого вмешательства в OCF:
1) Написать модуль, состоящий из одной процедуры
2) Найти точку входа в процедуру в HEX-редакторе. Она такая
Код:
push ebp
mov esp,ebp

3) Написать что-нибудь вроде этого
Код:
xor eax,eax
mov d,[eax],1

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


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 01 Ноябрь, 2007 20:46 
Аватара пользователя

Зарегистрирован: Вторник, 19 Сентябрь, 2006 21:54
Сообщения: 2463
Откуда: Россия, Томск
ScrollLock писал(а):
Есть ещё один способ "уронить" программу - с помощью прямого вмешательства в OCF:

Экий ты умный. Есть ещё один способ уронить программу - с помощью прямого вмешательства отвёрткой в блок питания.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 01 Ноябрь, 2007 22:53 

Зарегистрирован: Среда, 01 Август, 2007 00:13
Сообщения: 166
Цитата:
Экий ты умный. Есть ещё один способ уронить программу - с помощью прямого вмешательства отвёрткой в блок питания.

:D Но ведь задача была - не использовать модуль SYSTEM. Вот я и не использовал. Кстати, развалить саму среду у меня не получилось - она перехватывает исключения. А так я понимаю, что это брутальный способ.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Понедельник, 05 Ноябрь, 2007 02:11 
Аватара пользователя

Зарегистрирован: Суббота, 19 Ноябрь, 2005 15:59
Сообщения: 803
Откуда: Зеленоград
Trurl писал(а):
Понял почему не получается. Теперь не могу понять, как у меня получилось.
При передаче a[k] по ссылке, компилятор размещает адрес a в дополнительной локальной переменной.


Кажется, это самый простой способ сохранить репутацию оберонов как безопасных языков. :)
При передаче по ссылке переменной, входящей в состав структурной переменной, размещенной в динамической памяти, компилятор просто сохраняет копию указателя на структурную переменную в стеке (за исключением ситуаций, когда есть гарантия, что и без того на структурную переменную останется хотя бы один указатель), а после возврата из процедуры -- восстанавливает значение указателя стека.
Код:
VAR p: POINTER TO RECORD ... v: INTEGER; ... END;
...
PROCEDURE foo(VAR a: INTEGER);
BEGIN ... END foo;
...
(* здесь что-то вроде push p *)
foo(p.v);
(* здесь, например, add %sp,4,%sp *)
...
Есть ли лучший способ?


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Понедельник, 05 Ноябрь, 2007 17:12 
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9459
Откуда: Россия, Орёл
Vlad писал(а):
info21 писал(а):
Цитата:
А что при этом с производительностью GC становится (который в ББ и так не блещет)?

Еще как блещет. Только в реальных задачах, а не в дурацких тестах.

Понятно, значит доказать вы опять не можете.


Mark&Sweep даёт слабину на мелких короткоживущих объектах. Тогда хорошо работают поколения с маркирующе-копирующей сборкой в первом поколении. Для объектов с нормальным сроком жизни марирующе-копирующий сборщик, вообще говоря, ПРОТИВОПОКАЗАН.
Теперь остаётся только разобраться, откуда в той же Яве берётся прорва этих самых мелких объектов. Правильно, потому что любая требуха, созданная для передачи из процедуры в процедуру, или как сообщения, может быть создана только в куче - и плевать, что сразу же её потребуется собрать, но на стеке её не разместить - язык не позволяет :-р

Для Оберон-системы (в том числе для гуёвых прикладных приложений, либо сложной научной алготмики) такой режим выделения памяти совершенно нехарактерен. А в редких случаях, когда в отдельном месте такой режим надо задействовать, ставиться простенький буфер для переиспользования объектов конкретного типа.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Понедельник, 05 Ноябрь, 2007 17:19 
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9459
Откуда: Россия, Орёл
Вообще говоря, господа, strictStackSweep всё равно придётся переключать в FALSE (как и было сделано в ActiveBB). Потому что в многопоточной среде сборка мусора может начаться из другого потока в тот момент, когда наш работает по ссылке с полем динамического объекта или ячейкой динамического массива. И эта ссылка ОБЯЗАНА признаваться якорем, т.е. сборщик должен работать консервативно.

На быстродействие этот режим не влияет никак. Там в одном месте строгое сравнение с началом блока меняется на неравенство относительно его границ - и всего делов. Влияет только на консервативность :-) Т.е. в стеке может быть число-"обманка", которое будет трактоваться как якорь.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Понедельник, 05 Ноябрь, 2007 18:18 
Аватара пользователя

Зарегистрирован: Суббота, 19 Ноябрь, 2005 15:59
Сообщения: 803
Откуда: Зеленоград
Илья Ермаков писал(а):
Влияет только на консервативность :-) Т.е. в стеке может быть число-"обманка", которое будет трактоваться как якорь.

Верно ли я понимаю, что "радикальное" решение с предварительным сохранением указателя в стеке не стыкуется с однопроходностью компилятора?


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Понедельник, 05 Ноябрь, 2007 18:21 
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9459
Откуда: Россия, Орёл
Да вроде решение вполне нормальное.
Впрочем, я не компиляторщик (пока :-) ) и подробнее сказать не могу.
А вот на уровне рантайма, без модификации компилятора, решается только введением консервативности.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Понедельник, 28 Июль, 2008 22:27 

Зарегистрирован: Среда, 04 Июль, 2007 16:43
Сообщения: 247
Интересно, и что Ominc на это уже как-то прореагировал?


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Вторник, 29 Июль, 2008 00:13 
Аватара пользователя

Зарегистрирован: Суббота, 15 Март, 2008 20:00
Сообщения: 297
Откуда: Київ, Україна
В BlueButtle(A2) эффект повторяется :)
Может на www.ocp.inf.ethz.ch запостить?


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Вторник, 29 Июль, 2008 11:17 
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9459
Откуда: Россия, Орёл
Так.

Что-то я забыл: а в Активном Обероне может быть такая ситуация, что у потока есть только VAR-ссылка на переменную? Видимо, нет... В отличие от Active BlackBox-а, где активная процедура при старте вполне может получать такую ссылку, с проверкой, что адресуемый объект в куче...


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Суббота, 10 Январь, 2009 13:03 
Аватара пользователя

Зарегистрирован: Суббота, 15 Март, 2008 20:00
Сообщения: 297
Откуда: Київ, Україна
Сергей Губанов писал(а):
Вот так ещё проще:
Код:
MODULE TestCrash;

   IMPORT Log;

   PROCEDURE Do*; (* TestCrash.Do *)
      VAR a: POINTER TO ARRAY 100000 OF BOOLEAN;

      PROCEDURE Crash (VAR b: BOOLEAN);
      BEGIN
         REPEAT
            NEW(a);
            b := TRUE
         UNTIL a[0]
      END Crash;
   
   BEGIN
      NEW(a);
      Crash(a[0]);
      Log.String("Crashed!!!"); Log.Ln
   END Do;

END TestCrash.

Принципиально то, что переменная a объявлена внутри процедуры. Когда она глобальная вроде всё нормально.

Вот вернулся я к этому топику и хотел сказать, что ни кто не гарантирует инициализацию памяти при выделении!
Я даже был бы расстроен, если я выделяю большой блок памяти, а добрый компилятор мне все забивает нулями, когда мне это не нужно! :lol:


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Суббота, 10 Январь, 2009 13:29 
Аватара пользователя

Зарегистрирован: Вторник, 19 Сентябрь, 2006 21:54
Сообщения: 2463
Откуда: Россия, Томск
bohdant писал(а):
Вот вернулся я к этому топику и хотел сказать, что ни кто не гарантирует инициализацию памяти при выделении!
При выделении памяти под структуру, содержащую указатели, гарантируется, что все указатели будут = NIL.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Суббота, 10 Январь, 2009 13:58 
Аватара пользователя

Зарегистрирован: Суббота, 15 Март, 2008 20:00
Сообщения: 297
Откуда: Київ, Україна
Цитата:
При выделении памяти под структуру, содержащую указатели, гарантируется, что все указатели будут = NIL.

А где это написано? Просто интересно.


a[0]- не указатель a[0] - элемент вновь созданного массива


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 45 ]  На страницу Пред.  1, 2, 3  След.

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
cron
Вся информация, размещаемая участниками на конференции (тексты сообщений, вложения и пр.) © 2005-2025, участники конференции «OberonCore», если специально не оговорено иное.
Администрация не несет ответственности за мнения, стиль и достоверность высказываний участников, равно как и за безопасность материалов, предоставляемых участниками во вложениях.
Без разрешения участников и ссылки на конференцию «OberonCore» любое воспроизведение и/или копирование высказываний полностью и/или по частям запрещено.
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB