in reply to Re^2: Warnings not working on one machine
in thread Warnings not working on one machine

So, here are some examples of code producing different results on both machines. test2.pl runs alone by itself, test3.pl does the exact same tasks but uses the test3_utils.pl file. In both cases, warnings and variable contents differ per machine.
cat test2.pl #!/usr/bin/perl use strict; use warnings; use Cwd; use File::Basename; use List::Util qw(min max); use Math::Round; use Sort::Key::Natural qw(natsort); use Storable 'dclone'; use Sys::Hostname; use Term::ANSIColor; print "decimal places: ".length(("1" =~ /\.(\d*)/)[0])."\n"; print "decimal places: ".length(("0.123" =~ /\.(\d*)/)[0])."\n"; my $line = "apple="; my $second_part = (split(/=/, $line))[1]; my $second_part_components_count = (length $second_part > 0 ? scalar ( +split(/;/, $second_part)) : 0); print "done\n"; cat test3.pl #!/usr/bin/perl use strict; use warnings; use Cwd; use File::Basename; use List::Util qw(min max); use Math::Round; use Sort::Key::Natural qw(natsort); use Storable 'dclone'; use Sys::Hostname; use Term::ANSIColor; require "test3_utils.pl"; do_foo(); do_bar(); print "done\n"; cat test3_utils.pl #!/usr/bin/perl sub do_foo { print "decimal places: ".length(("1" =~ /\.(\d*)/)[0])."\n"; print "decimal places: ".length(("0.123" =~ /\.(\d*)/)[0])."\n"; } sub do_bar { my $line = "apple="; my $second_part = (split(/=/, $line))[1]; my $second_part_components_count = (length $second_part > 0 ? scal +ar (split(/;/, $second_part)) : 0); } 1; # need to end with a true value

The scripts are copied to the second computer (SciLnx) where they produce different results:

me@UbuntuMachine: ./test2.pl Use of uninitialized value in concatenation (.) or string at ./test2.p +l line 14. decimal places: decimal places: 3 Use of uninitialized value $second_part in numeric gt (>) at ./test2.p +l line 19. done me@UbuntuMachine: ./test3.pl decimal places: decimal places: 3 done me@SciLnxMachine: ./test2.pl Use of implicit split to @_ is deprecated at ./test2.pl line 19. Use of uninitialized value in length at ./test2.pl line 14. decimal places: 0 decimal places: 3 Use of uninitialized value $second_part in length at ./test2.pl line 1 +9. done me@SciLnxMachine: ./test3.pl decimal places: 0 decimal places: 3 done
I would expect the same results and the same warnings on both machines. To my surprise, neither is the case. The SciLnx is returning 0 where the Ubuntu machine is returning nothing.

The software in question is distributed to partners, it is important that it does what we expect. Is there any way to investigate what is causing this behavioural difference?

Replies are listed 'Best First'.
Re^4: Warnings not working on one machine
by poj (Abbot) on Jan 26, 2018 at 13:57 UTC

    In Perl 12 Delta one of the Other potentially incompatible changes is ;

    length undef now returns undef.

    Update Possible fix ? length(("1" =~ /\.(\d*)/)[0] || '')

    poj
Re^4: Warnings not working on one machine
by hippo (Archbishop) on Jan 26, 2018 at 13:57 UTC
    In both cases, warnings and variable contents differ per machine.

    Not quite. If you look closely at your outputs, the warnings in test3.pl do not differ between the machines. This is because there are no warnings because the code which would generate them is in test3_utils.pl which does not have warnings enabled.

    But not having the warnings enabled is a bad thing because you would miss important points like "Use of implicit split to @_ is deprecated at ./test2.pl line 19." in the older perl. Since you don't see this in the newer perl it's safe to say that it has moved from "deprecated" to "deleted" and hence the code behaves differently. When you first saw that warning in the older perl version you should have taken steps then to code around it and you might not have the problem now in the newer perl version.

    Always use warnings and always fix any which are reported.

    Update: Here's an example rewrite of test2.pl which produces no warnings and the same output on both v5.10.1 or v5.20.3:

    use strict; use warnings; sub ndp { $_ = shift or return 0; /\.(\d*)/ and return length ($1); return 0; } print "decimal places: " . ndp ('1' ) . "\n"; print "decimal places: " . ndp ('0.123') . "\n"; my $line = "apple="; (undef, my $second_part) = split (/=/, $line); my $second_part_components_count = length $second_part ? scalar (my @f +oo = split /;/, $second_part) : 0; print "done\n";

    No doubt it could be neater but hopefully it illustrates some approaches for you.

      Thanks for your replies. I guess I have to put the use warnings; into both the calling script and the called utilities library, which is what I have now done.

      I was hoping the use warnings; in the calling script would have been enough to ensure all called libraries had the same warnings behaviour when used by that script. That way the same library could be used by different scripts with different warnings behaviour. Not sure if they had other concerns in mind when they decided to make it like this, but I'm happy that I now finally know what's going on and how to make it work for me.

      Thank you for your assistance!

        Have you read Reporting Warnings from a Module? This can be used to achieve precisely what you have outlined as your goal here. eg:

        package Foo; use warnings::register; sub bar { $^W = warnings::enabled () ? 1 : 0; print $baz; }; 1; package main; use warnings 'Foo'; Foo::bar (); no warnings 'Foo'; Foo::bar ();

        If you run this you will only see one occurrence of the warning Use of uninitialized value $Foo::baz in print at /tmp/warnshow.pl line 9. which is caused by the first call to Foo::bar (). The second call does not generate the warning. HTH.