dhannotte has asked for the wisdom of the Perl Monks concerning the following question:

I recently decided it was time to upgrade my Windows 64-bit version of ActivePerl from 5.10.1.1007 to 5.22.2.2203. I'm now getting a new error message when I try to "use" the collection of generally useful subroutines I keep in Plx.pm:
E:\!!!dh()testplx Can't use 'defined(@array)' (Maybe you should just omit the defined()? +) at (#2) line 2842. Compilation failed in require at C:\!dh\DH\COM\SRC\testplx.pl line 4. BEGIN failed--compilation aborted at C:\!dh\DH\COM\SRC\testplx.pl line + 4.
This is testplx.pl in its entirety:
use Carp; $SIG{__WARN__} = \&carp; $SIG{__DIE__} = \&confess; use Plx;

Line 2842 of Plx.pm is: my ($err_num, $err_txt);

There are 101 occurences of the string "defined" in 98 lines of Plx.pm.

1) Why isn't Carp identifying the correct line?

2) Besides going through 101 occurences, how can I find where (and WHAT) this error really is?

Thanks, everybody!

Replies are listed 'Best First'.
Re: New error message in ActivePerl 5.22
by dave_the_m (Monsignor) on Jan 16, 2017 at 16:31 UTC
    Can't use 'defined(@array)' (Maybe you should just omit the defined()?) at (#2) line 2842 Perl doesn't normally produce error messages where the filename is listed as (#2). Some possibilities for why this might be happening are:

    some code is being read from a file literally called '(#2)';

    A source file has a line directive which changes the reported filename:

    # line 1234 "(#2)" .... if (defined @a) {1; }

    You have a $SIG{__DIE__} which is in some way modifying the error message.

    Dave.

Re: New error message in ActivePerl 5.22
by stevieb (Canon) on Jan 16, 2017 at 14:49 UTC
    Per perldelta 5.22, defined @array; was deprecated and now throws fatal error:

    "defined(@array) and defined(%hash) are now fatal errors. These have been deprecated since v5.6.1 and have raised deprecation warnings since v5.16.".

    I would do a grep on each file at a time for defined(@, verify what you get back is what you can do a global search and replace on, and do a s/defined(@/(@/g (in vi/vim: :%s/defined(@/(@/g. This will remove just the defined part, leaving just if (@array), which will check to see if there are any elements. Another way is to check defined on the first element: if (defined $array[0]).

    update: defined $array[0] likely isn't a safe approach, as per a msg, the first element may be undefined, while latter elements may exist and be defined./update

    Make a backup (or do a commit) before making any changes, so if things go downhill, you can revert the file back easily. After the global sweep, clean up any stragglers manually.

Re: New error message in ActivePerl 5.22
by kcott (Archbishop) on Jan 17, 2017 at 00:11 UTC

    G'day dhannotte,

    "1) Why isn't Carp identifying the correct line?"

    Perl will do its best to parse whatever code you provide. When it decides it definitely can't continue, it provides the line number where it gave up. It could be the problem line; it could be within the next few lines; it could be many pages of code later. Whilst it obviously depends on the code in question, the second case is probably the most common; the first case is less common; and, for the third case, you'll often get some sort of hint (e.g. Might be a runaway multi-line %s string starting on line %d).

    So, for your posted problem, look at the lines just before 2842 for code like "defined @some_array_name".

    "2) Besides going through 101 occurences, how can I find where (and WHAT) this error really is? "

    You can look in perldiag for diagnostic messages. Here you'll find the error message you posted along with a description of the problem.

    You've shown "testplx.pl in its entirety". That code is missing these two lines (which should be at the top):

    use strict; use warnings;

    [See strict and warnings for details.]

    As a developer tool (i.e. don't include this in production code), you can also use the diagnostics pragma: this will give you the full description associated with the diagnostic message.

    I suspect your other code is also missing one, or both, of those lines. Plx.pm certainly doesn't have warnings: if it did, you would have received deprecation warnings (not errors) and could have fixed them as they occurred. Presumably, after receiving the first few, you would have stopped making that mistake.

    Rather than looking at every instance of defined in your code, many of which may be perfectly fine (e.g. defined $some_scalar), it might be easier to keep running your script and fixing each as they occur. Bear in mind that these are fatal errors; each will be reported separately, even if they occur on the same line:

    $ perl -E 'my (@x, @y); say defined(@x) ? 1 : 0; say defined(@y) ? 1 : + 0' Can't use 'defined(@array)' (Maybe you should just omit the defined()? +) at -e line 1. $ perl -E 'my (@x, @y); say @x ? 1 : 0; say defined(@y) ? 1 : 0' Can't use 'defined(@array)' (Maybe you should just omit the defined()? +) at -e line 1. $ perl -E 'my (@x, @y); say @x ? 1 : 0; say @y ? 1 : 0' 0 0

    — Ken

      Thanks everyone for your excellent advice. Unfortunately, I've spent almost all of this year in hospitals and rehab centers and no longer have the time to hunt down each and every anomaly that has made my labor of love an inoperable monstrosity. I'm putting my affairs in order and need to fix some critical bugs in this product before it's too late. Please, can someone provide me with a version of 5.10 so I can release my software before my chance to contribute something to this sad world is over. Thanks.
        Can't help with ActivePerl (but their page mentions 5.10 as supported in their enterprise edition). I'd go for StrawberryPerl; on their releases page they have 5.10.1.5 (May 2011). The ZIP edition (as opposed to the MSI installer) doesn't need admin privileges and therefore will not mess with the system's internals, which is why i prefer this method.

        Then there is berrybrew, which allows you to use multiple (Strawberry) Perl versions concurrently, so you could first get your scripts to work again using 5.10 and later switch to a newer Perl (and back and forth).