Спасибо! Очень много интересной информации вы мне дали. Пойду изучать...
Не могли бы вы мне подсказать файл, в котором перл генерирует опкод для goto?

>Во втором случае никакой local работать не будет, вернее будет...
local $DB::single = $DB::single +0; работал и работает отлично и в дебаг режиме 
тоже (см. ниже)

>Мне кажется, что для хранения текущего состояния в своём дебаггере
Как раз не текущее состояние было нужно, а n фреймов назад...


У меня в дебагере что-то наподобие:
sub sub {
     local $DB::single =  $DB::single +0; # без 0 не работает :?
     return &$DB::sub;
 }

Где-то внутри вызываемой функции с именем "$DB::sub" я делаю $DB::single = 0 и 
автоматом останавливаюсь на первом операторе вне этой функции. Т.е. для кода:
sub t{ $DB::single = 0; }
t();
$x++; <<< останавливаюсь тут

Останавливаюсь потому, что после того как отработает 'return  &$DB::sub' перл 
восстановит старое локализированное значение $DB::single в TRUE
и вызовется DB::DB на первом опкоде после возврата, те. '$x++'

Но если бы мы хотели выйти на 2 фрейма вверх?
То нам нужно, чтобы старое локализированное значение $DB::single восстановилось 
в FALSE

Как поменять старое локализированное значение? - Взять ссылку на него...
Получается примерно такое:
sub sub {
     $#DB::stack = $DB::deep;
     $DB::stack[-1] =  { single => \$DB::single };

     local $DB::single =  $DB::single +0;
     local $DB::deep =  $DB::deep +1;
     return &$DB::sub;
}

sub t1 { $DB::stack[-1]{ single } =  0; $DB::single =  0; }  #DEEP 2
sub t2 { t1(); $y++; }  # DEEP 1
t2(); #DEEP 0
$x++; 

Если бы мы шли в функцию t1 пошагово, то было бы локализировано 2 значения 
$DB::single, это единицы.
[
   { single => \1 }
   { single => \1 }
]

после выполнения t1 стэк выгледел был бы так:
[
   { single => \1 }
   { single => \0 }
]

Соответственно после выхода из t1 перл бы востанавливал в $DB::single не в  
единицу, а в 0,   а это бы позволило нам выйти из t2 тоже и остановиться на $x++

И теперь мне понятно (благодаря вашему объяснению), что из-за магии 
$DB::single, когда мы делаем ${ $DB::stack[-1]{single} } = 0, то меняются все 
значения в стеке, а не только указанное, т.е. получаем:
[
   { single => \0 }
   { single => \0 }
]

соответственно вываливаемся полностью из программы...

Я предпологаю, что должна быть возможность через XS обойти магию и присвоить 0 
в правильную ссылку. Не могли бы вы порекомендовать какие нибудь хорошие 
мануалы по XS?


PS. Сейчас пока обхожусь костылём. Завожу переменную, в которой хранится 
значение на сколько уровней нужно поднятся и в sub DB::DB делаю 
sub DB {
   if( $DB::level-- != 1 ) {
       $DB::single =  0;
       return;
   }
}


Соответсвенно в t1:
sub t1 { $DB::level =  2; $DB::single =  0; }
Недостаток этого метода, наверное, небольшой проигрыш в скорости работы, по 
сравнению с "правильным" методом, но выбирать не приходиться (((

PSS. Тут для наглядности и простоты примеров я изменял значения из DB:: прям в 
коде скрипта, но в боевом примере этого добиваюсь с помощью комманд дебагера s 
n r

Вы писали 6 января 2016 г., 18:45:53:

VT> Ну вот это уже интереснее )

VT> Так вот:
VT> 1. Без дебаггера, $DB::single обычный скаляр, с ним всё происходит как
VT> надо (в вашем случае это был $DB::x,  об этом чуть ниже).
VT> $ perl -MDevel::Peek -e'Dump($DB::single)'
VT> SV = NULL(0x0) at 0x7f882b82dc60
VT>   REFCNT = 1
VT>   FLAGS = ()

VT> 2. С подключенным дебаггером.
VT> $ perl -MDevel::Peek -d -e'Dump($DB::single)'
VT>   DB<1> c
VT> SV = PVMG(0x7fc78a025460) at 0x7fc78a004a30
VT>   REFCNT = 1
VT>   FLAGS = (GMG,SMG,IOK,pIOK)
VT>   IV = 0
VT>   NV = 0
VT>   PV = 0
VT>   MAGIC = 0x7fc789c052e0
VT>     MG_VIRTUAL = &PL_vtbl_debugvar
VT>     MG_TYPE = PERL_MAGIC_debugvar(*)

VT> Во втором случае никакой local работать не будет, вернее будет... в
VT> штатном режиме (это можно увидеть, если вставить Dump в ваш код), но
VT> толку нет, потому что к значениям из слотов SV не будет доступа,
VT> вместо этого будет вызываться метод из VTBL магический, который...
VT> возвращает актуальное значение. (это примерное объяснение, я редко
VT> лазил в эту область и внимательно сейчас читать исходники нет ни
VT> времени ни желания :-)

VT> Всю магию, которую вешает дебаггер можно посмотреть в perl.c где-то в
VT> р-не строки 4000, функция Perl_init_debugger. Соотвественно, те
VT> символы, на которых магия могут работать не нормально: DB::single,
VT> DB::trace, DB::signal.

VT> Мне кажется, что для хранения текущего состояния в своём дебаггере,
VT> можно использовать нормальные свои переменные в пакете DB, главное не
VT> пересечься с уже используемыми перлом.

VT> 2016-01-06 22:38 GMT+03:00 KES <[email protected]>:
>> Я извиняюсь. Упустил важный момент. Вот полный код:
>> $ cat Devel/DB.pm
>> package DB;


>> sub DB::DB {
>> }

>> sub sub {
>>     {
>>         $DB::single = 7; my $x = \$DB::single;
>>         print "Before: ". \$DB::single ." <<$x $$x\n";
>>         local $DB::single = 0;
>>         print "After: ". \$DB::single ." <<$x $$x\n";
>>     }

>>     return &$DB::sub;
>> }

>> 1;

>> $ perl -d:DB -e 'sub t{} t()'

>> $ perl -v
>> This is perl 5, version 22, subversion 0 (v5.22.0) built for x86_64-linux

>> PS. Думаю в ближайшее мне придется очень глубоко копнуть в исходники перл, 
>> т.к. в дебаг режиме шероховатость на шероховатости :`-(
>> --
>> Moscow.pm mailing list
>> [email protected] | http://moscow.pm.org



VT> -- 
VT> Vladimir Timofeev <[email protected]>



-- 
С уважением,
 Eugen                          mailto:[email protected]

-- 
Moscow.pm mailing list
[email protected] | http://moscow.pm.org

Ответить