Perl debugger - breaks error (exception)?

Consider this small perl program, test.pl :

 #!/usr/bin/env perl use warnings; use strict; use Number::Format qw(:subs); # sudo perl -MCPAN -e 'install Number::Format' my $tstr = ""; my $numFormatter = new Number::Format(); for (my $ix=0; $ix<20; $ix++) { $tstr = $tstr . int(rand(10)); my $ftstr = $numFormatter->format_number($tstr, 2, 1); print "ix: $ix ; in: $tstr ; out: $ftstr\n"; } 

If I run it, it will fail. If I run it in the Perl debugger using perl -d , it will also fail with an error:

 $ perl -d test.pl Loading DB routines from perl5db.pl version 1.39_10 Editor support available. Enter h or 'hh' for help, or 'man perldebug' for more help. main::(test.pl:6): my $tstr = ""; DB<1> c ix: 0 ; in: 6 ; out: 6.00 ix: 1 ; in: 63 ; out: 63.00 ix: 2 ; in: 637 ; out: 637.00 ix: 3 ; in: 6379 ; out: 6,379.00 ix: 4 ; in: 63790 ; out: 63,790.00 ix: 5 ; in: 637906 ; out: 637,906.00 ix: 6 ; in: 6379062 ; out: 6,379,062.00 ix: 7 ; in: 63790624 ; out: 63,790,624.00 ix: 8 ; in: 637906246 ; out: 637,906,246.00 ix: 9 ; in: 6379062467 ; out: 6,379,062,467.00 ix: 10 ; in: 63790624671 ; out: 63,790,624,671.00 ix: 11 ; in: 637906246715 ; out: 637,906,246,715.00 ix: 12 ; in: 6379062467152 ; out: 6,379,062,467,152.00 ix: 13 ; in: 63790624671522 ; out: 63,790,624,671,522.00 round() overflow. Try smaller precision or use Math::BigFloat at test.pl line 11. at /usr/local/share/perl/5.18.2/Number/Format.pm line 535. Number::Format::round('Number::Format=HASH(0x9d0b6cc)', 637906246715226, 2) called at /usr/local/share/perl/5.18.2/Number/Format.pm line 601 Number::Format::format_number('Number::Format=HASH(0x9d0b6cc)', 637906246715226, 2, 1) called at test.pl line 11 Debugged program terminated. Use q to quit or R to restart, use o inhibit_exit to avoid stopping after program termination, hq, h R or ho to get additional info. DB<1> p $ix DB<2> 

... but when it fails, it does not stop on the line of failure, as gdb with program C says, maybe the program terminates again, and therefore I have no context variables to check.

Of course, such a cycle can be performed thousands of times, so setting a breakpoint in the problem line and executing c ontinue manually will not help here ...

Is there a way for the Perl debugger to crash the program on error / exception, so that the context of the local variable is saved to check the variables there?

+6
source share
2 answers

Wrap the violation string in eval and set $DB::single when $@ installed:

 #!/usr/bin/env perl use warnings; use strict; use Number::Format qw(:subs); # sudo perl -MCPAN -e 'install Number::Format' my $tstr = ""; my $numFormatter = new Number::Format(); for (my $ix=0; $ix<20; $ix++) { $tstr = $tstr . int(rand(10)); my $ftstr = eval { $numFormatter->format_number($tstr, 2, 1); }; $DB::single = 1 if $@ ; print "ix: $ix ; in: $tstr ; out: $ftstr\n"; } 

Then

 % perl -d test.pl Loading DB routines from perl5db.pl version 1.49 Editor support available. Enter h or 'hh' for help, or 'man perldebug' for more help. main::(test.pl:6): my $tstr = ""; DB<1> r ix: 0 ; in: 7 ; out: 7.00 ix: 1 ; in: 71 ; out: 71.00 ix: 2 ; in: 715 ; out: 715.00 ix: 3 ; in: 7153 ; out: 7,153.00 ix: 4 ; in: 71537 ; out: 71,537.00 ix: 5 ; in: 715379 ; out: 715,379.00 ix: 6 ; in: 7153794 ; out: 7,153,794.00 ix: 7 ; in: 71537941 ; out: 71,537,941.00 ix: 8 ; in: 715379417 ; out: 715,379,417.00 ix: 9 ; in: 7153794174 ; out: 7,153,794,174.00 ix: 10 ; in: 71537941740 ; out: 71,537,941,740.00 ix: 11 ; in: 715379417408 ; out: 715,379,417,408.00 ix: 12 ; in: 7153794174086 ; out: 7,153,794,174,086.00 ix: 13 ; in: 71537941740864 ; out: 71,537,941,740,864.00 main::(test.pl:13): print "ix: $ix ; in: $tstr ; out: $tstr\n"; DB<1> print $tstr 715379417408646 DB<2> 

What is a Heck?

There are two principles behind magic:

  • Prevention of fatal exceptions (e.g. catching exceptions)
  • Stopping the debugger at a specific point in the code without repeated steps

To catch the exception, use the eval BLOCK construct. This will save the exception in the $@ variable. If $@ not an empty string, an exception is thrown. Please note that the code above, although idiomatic, is not entirely correct; if excluded string 0 selected, it will be ignored (because if 0 will be false). Perl exception handling is complex. Try::Tiny has a good discussion.

Now that the exception is no longer fatal, how to stop the debugger? There are several ways to do this. In this example, the variable $DB::single , which, if true, signals the end of debugging. The downside is that you have to edit your code to influence this behavior. Another option is to set a breakpoint with the condition :

 % perl -d test.pl Loading DB routines from perl5db.pl version 1.49 Editor support available. Enter h or 'hh' for help, or 'man perldebug' for more help. main::(test.pl:6): my $tstr = ""; DB<1> b 11 $@ ne '' DB<2> r [... output as above ...] main::(test.pl:11): my $ftstr = eval { $numFormatter->format_number($tstr, 2, 1); }; DB<2> p $tstr 3247014520717436 

See the perl debugger documentation for more details.

+6
source

Capturing a stamp using eval{} and $DB::single = 1 if $@ ; is a good trick, but if you want to get to the source of the problem in the library, you need to set a breakpoint at the place where the error is thrown.

Is executed here

  DB<1> b Carp::croak DB<2> c Carp::croak(/opt/local/lib/perl5/5.22/Carp.pm:166): 166: sub croak { die shortmess @_ } DB<3> T @ = DB::DB called from file '/opt/local/lib/perl5/5.22/Carp.pm' line 166 . = Carp::croak('round() overflow. Try smaller precision or use Math::BigFloat') called from file '/opt/local/lib/perl5/site_perl/5.22/Number/Format.pm' line 535 $ = Number::Format::round(ref(Number::Format), 637906246715227, 2) called from file '/opt/local/lib/perl5/site_perl/5.22/Number/Format.pm' line 601 $ = Number::Format::format_number(ref(Number::Format), 637906246715227, 2, 1) called from file 'mytest.pl' line 12 
+5
source

All Articles