我如何警告`perl -c`中的函数用法?

时间:2014-11-10 12:38:56

标签: perl debugging compiler-warnings

我们的代码库包括各种只应用于测试的调试钩子。作为一个说明性的例子:

sub example {
   my ($arg) = @_;
   my $result = do_something_with($arg);
   debug_dump_values($arg); # debugging code
   return $result;
}

当然,不应提交(甚至部署)此类调试代码。有没有办法在perl -c运行此代码时生成警告?

的内容
Debug function debug_dump_values() called at example.pl line 4.

实现运行时警告是非常简单的:

sub debug_dump_values {
    carp "Debug function debug_dump_values() called";
    ...
}

但我希望通过syntax check plugin在我的文本编辑器中显示一条警告,因此它需要是一个“编译时”警告。

3 个答案:

答案 0 :(得分:1)

我认为这不是一件容易实现的事情 - 如果没有一些重要的编码风格重新调整,它就不可能实现。

我能想到的方法:

点击你的调试工具'代码进入一个单独的模块。

在模块中嵌入一个警告,指示它已启用 - 嵌入“开始”状态。块。 (这不一定会告诉你哪个子被调用,也不知道在哪里)

E.g。

BEGIN { 
    carp "Debugging module is imported" 
}

这样做的好处可能是 - 您可以进行调试'并且“不调试'模块,并在两者中都有相同的子。 '不调试'会放入虚拟潜艇。

然后,您可以使用B::Lint验证您的模块并检查是否已定义了所有模块:

perl -MO=Lint[,OPTIONS] foo.pl

undefined-subs This option warns whenever an undefined subroutine is invoked. This option will only catch explicitly invoked subroutines such as foo() and not indirect invocations such as &$subref() or $obj->meth() . Note that some programs or modules delay definition of subs until runtime by means of the AUTOLOAD mechanism

通过参考分配您的子。

编辑:不像我想的那样工作 - 有一个声明匿名潜艇并在' BEGIN'内创建参考的概念。块 - 这并不像我想的那样有效 - 它只是在运行时出错,因为你得到了范围错误。

我能提供的最好的是:

use strict;
use warnings;

my $debug = 1;

##debug code bit. 
#Comment out if not needed
my $debug_sub = gimme_debug();

sub gimme_debug {
    if ( $debug ) { 
        warn "Debugging enabled\n"; 
        return sub { print "Got values of :", @_, "\n"; };
    }
    else { warn "Debug subroutine defined with debug disabled!" };
}

#... way down code ... 

&$debug_sub ( "Some input" );

如果删除声明,那么您将收到编译时警告,因为$debug_sub未声明。这可能与上述结合,例如将其捆绑在模块或对象中。

自动化测试

它并没有专门针对您提出的问题,但无论如何您可能还想考虑它。自动测试代码/模块。例如,使用TAP::Harness。它比你要问的要复杂和密集,但是有一些能够自动捕获调试代码(以及以其他方式验证代码的各个组件)的东西可能是正确的'对& #39;这样做的方法。

我也听说过(但没有做太多)Class::Inspector这可能适合您的需要。 但我认为在一个相当基础的层面 - 你在编译时没有检查过什么,因为在没有实际运行的情况下评估哪些代码实际被调用是非常困难的。码。因此,您所做的任何事情都是您必须手工管理的事情。以某种方式。

The Halting Problem

"在可计算性理论中,暂停问题是从任意计算机程序和输入的描述中确定程序是否将完成运行或继续永久运行的问题。

Alan Turing在1936年证明,不存在解决所有可能的程序输入对的暂停问题的通用算法。证明的一个关键部分是计算机和程序的数学定义,它被称为图灵机;暂停问题对于图灵机来说是不可判定的。这是决策问题的第一个例子之一。"

因此,如果您确实想出了一个很好的解决方案 - 可能会提供有用的大奖:)。

答案 1 :(得分:0)

在我的开发环境中,我遇到了类似的问题。我的方法是使用C风格的#ifdef和#endif注释来包围调试代码,如下所示:

sub example {
   my ($arg) = @_;
   my $result = do_something_with($arg);
#ifdef DEBUG
   debug_dump_values($arg); # debugging code
#endif
   return $result;
}

作为构建版本的一部分,程序ppp.pl(我写的)在每个Perl源文件上运行,并注释掉(或删除)调试代码。一个简单的ppp.pl很容易编写。如果有人有兴趣,我可以在公共场所发布我的版本。

答案 2 :(得分:0)

如果您使用Log :: Log4perl并创建一个名为$logger的记录器,那么您可以通过$logger->is_debug()检查调试模式,只有在启用调试级别时才会调用该函数

然后您的代码就可以保留,但只能在调试时调用。

即。

sub example {
   my ($arg) = @_;
   my $result = do_something_with($arg);
   debug_dump_values($arg) if $logger->is_debug(); # debugging code
   return $result;
}