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

Recently I had a CGI program start throwing error 500's. I tracked it down to a misspelled function name in a block that handles an obscure error condition. I fixed it but I'm wondering if there is a tool (or switch) that will catch "Undefined subroutine" errors before the code goes to testing.

Replies are listed 'Best First'.
Re: Undefined Subroutine errors
by imp (Priest) on Jul 17, 2006 at 20:20 UTC
    Not that I am aware of.

    There are several reasons why undefined functions are not caught at compile time, here are a few:

    Autoloading
    See AUTOLOAD in the perlsub document.

    Conditional calling of functions

    sub test { my $object = shift; $object->somefunction if $object->can('somefunction'); }
    In the above example somefunction is only called if the passed object has this method defined.

    This is useful when you might have different objects being used that conform to a common interface, but have some additional capabilities.

    Also useful when you might be dealing with older versions of a module that do not support certain methods.

    Checking if an object can do something is generally preferrable to checking if an object is something

      Actually there is one very reliable way to detect these situations - a comprehensive test suite.

      Your test suite should have a test (or several) written for each of the cases that should cause a failure. If this test suite was run before each release you would catch the error that this post references.

      Writing a compehensive set of tests can be an intimidating task, but the amount of time it will save you in the long run is well worth it.

      Here is an article describing perl best practices, it has 10 tips from Damian Conway's excellent Perl Best Practices book.

        I can't claim the test suite was comphrensive since it obviously wasn't. I've added a case that will cause the branch in question to be taken. I'll take a look at he article you referenced, thanks.
      Run-time loaded functions and run-time generated function calls form the minority of functions and calls. A tool that can't handle those exceptions might exist and would still be valuable.
Re: Undefined Subroutine errors
by davido (Cardinal) on Jul 18, 2006 at 06:06 UTC

    You could do an analysis of the output from perl -MO=Xref yourfile.pl. If there is a subroutine listed in the "Subroutine (main), Package main" section that's not listed in the "Subroutine definitions, Package main" section, that's a possible problem to look into. The same goes for other packages too. I'm just theorizing here, as I'm not fully up to speed on B::Xref, but it does look like a good place to start if you simply wish to check to see if subroutines being used match subroutines actually defined.

    This doesn't get you very far with object method calls though. ...I guess that's what comprehensive test suites are for. ;)


    Dave

Re: Undefined Subroutine errors
by Herkum (Parson) on Jul 17, 2006 at 20:23 UTC
    When I run this script,
    #!/usr/bin/perl -w use strict; _undef_subroutine(); warn "Got here\n";
    I get this error,
    Undefined subroutine &main::_undef_subroutine called at C:\temp\undef. +pl line 4.

    Are you talking about a checking the syntax without running the script? Komodo has decent syntax checking but I am not sure exactly what you are looking for.

    Did you write any tests for your code? If you had it probalbly would have shown up there.

Re: Undefined Subroutine errors
by davorg (Chancellor) on Jul 18, 2006 at 08:13 UTC
Re: Undefined Subroutine errors
by blahblahblah (Priest) on Jul 17, 2006 at 23:52 UTC
    quick update: I just re-read your question and realized that you're not looking for run-time catching; you want something earlier. So my post doesn't answer your question. However, you still might find it an interesting way to deal with the run-time problem.

    We have a universal AUTOLOAD function in our app which catches these errors and prints a nice message. I'm at home, so I don't have the code in front of me, but I remember that I got the idea from the perl cookbook. I just found the table of contents on O'Reilly's site: it looks like chapter 10.15 is what I'm thinking of.

    We've had our AUTOLOAD for several years, and it does a few nice things besides catching our sloppy mistakes. However, it has a lot of disadvantages, like killing inheritance (which never used to bother us because none of our code was OO), and encouraging sloppy programming, so it's a mixed blessing.

    -Joe

Re: Undefined Subroutine errors
by duff (Parson) on Jul 18, 2006 at 03:20 UTC

    I wonder if PPI can distinguish between a subroutine definition and a subroutine call. If so, surely Perl::Critic can be made to look for subroutines that are called but never defined. Of course, this will give lots of false positives under certain circumstances, but it would still be better to have the option to check for such things.

Re: Undefined Subroutine errors
by swampyankee (Parson) on Jul 18, 2006 at 17:23 UTC

    Could B::Lint catch these? It does have an option for undefined_subs, so it may be worth a try.

    Also, remember what was said by (I believe) Dijkstra: "Program testing can be used to show the presence of bugs, but never to show their absence!"

    In other words, don't rely on testing to the exclusion of code reviews, verification tools, etc.

    emc

    e(π√−1) = −1
A reply falls below the community's threshold of quality. You may see it by logging in.