1

我编写了一个 perl 脚本来合并来自不同机器的 gcov 文件。下面是我为合并编写的子程序。

sub merge_gcov()
    {
        open(FILE1, "<$_[0]") or die "can not open file";
        open(FILE2, "<$_[1]") or die "can not open file";
        open(FILE3, ">$_[2]") or die "can not open file";
        my ($line1, $line2 , $flag );
        while ( 1 )
        {  
            $line1 = <FILE1>; # read them each
            $line2 = <FILE2>;
            last unless ( $line1 || $line2 ); # if both empty exit loop
            #
            # otherwise test for which one just finished
            #
            unless( $line1 )
            {
                $flag = 1;
            last;
            }
            unless( $line2 )
            {
                $flag = 2;
            last
            }   
            #
            # now do the voodo on the two lines
            #
            chomp($line2);
            chomp($line1);
            if($line1=~/^\s*-/ and  $line2 =~/^\s*-/)  
            {   
                print FILE3 "$line1\n";
            }
            elsif($line1=~/^\s*#####/ and  $line2 =~/^\s*#####/) 
            {      
                print FILE3 "$line1\n";
            }
            elsif($line1=~/^\s*#####:\s{0,}(\d{1,})/ and  $line2 =~/^\s{0,}(\d{1,})/) 
            {     
                print FILE3 "$line2\n"
            }
            elsif($line1=~/^\s{0,}(\d{1,})/ and  $line2 =~/^\s*#####:\s{0,}(\d{1,})/) 
            {  
                print FILE3 "$line1\n"
            }
            elsif($line1=~/^\s{0,}(\d{1,})/ and  $line2 =~/\s{0,}(\d{1,})/) 
            { 
                my @values1 =  split(/:/, "$line1");
                my @values2 =  split(/:/, "$line2");
                print FILE3 ("      ",$values1[0]+$values2[0]),":","$values1[1]:","$values1[2]\n";
            }
            else
            {  
                print FILE3 "$line1\n";
                print FILE3 "$line2\n";
             }

        }
    close(FILE3);
    }

合并正确完成,但合并后我得到以下错误....

Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 284046 (#1)
Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 284414 (#1)
Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 302995 (#1)
Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 311633 (#1)
Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 311962 (#1)
Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 321536 (#1)
Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 323445 (#1)
Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 329553 (#1)
Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 336009 (#1)
Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 336330 (#1)
Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 338188 (#1)
Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 343170 (#1)
Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 349037 (#1)
Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 349610 (#1)
Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 633937 (#1)
Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 634509 (#1)
Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 634877 (#1)
Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 653458 (#1)
Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 662096 (#1)
Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 662425 (#1)
Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 671999 (#1)
Use of uninitialized value in concatenation (.) or string at

我知道当我不使用警告时我没有收到这些警告但是有没有其他方法可以删除这些警告。

第 226 行是:print FILE3 (" ",$values1[0]+$values2[0]),":","$values1[1]:","$values1[2]\n";

4

2 回答 2

0

您测试未初始化的一行或另一行,但您从不使用该信息,因此您undef在 final 中打印了一个与换行符连接的行else;这是您的警告的来源。

您的gcov文件实际上有一堆多余的换行符,这是由一个文件首先用完引起的,每个不匹配的行一个。它们之所以有效,是因为gcov它接受的内容非常宽容,或者因为gcov当它看到第一个裸换行符时停止静默读取输入。第一个很棒;第二个非常糟糕。

为了解决这个问题,我们需要弄清楚我们期望在哪里拥有一个undef,以及当我们找到一个时要做什么。这段代码可以undef在我们到达每个文件$line1$line2末尾时生成。让我们看看你如何使用这些来查看哪些地方undef可以,哪些地方不行。

  1. 测试两行是否为假(例如undef):这是undef.
  2. 设置$flag:很好用,但逻辑​​不好,因为你再也不会使用$flag了。
  3. 模式匹配:很好的用法,因为模式匹配不应该(并且确实)失败,这对您的代码是正确的。
  4. 打印一行可能是undef: bad usage,因为这会生成警告并输出一个额外的空换行符。

因为模式匹配都将失败undef,所以您可以完全跳过设置的代码$flag并使最后一个else看起来像这样:

...
else {
    # One or the other file has run out already. Note that
    # the $line variables being undef here is OK because that's
    # an expected possible value that we're actually testing for.
    # We could used "defined $lineX" but since undef itself is 
    # false, this is okay.
    print FILE3 "$line1" if $line1;
    print FILE3 "$line2" if $line2;
}

现在进行一些undef哲学思考。

未初始化的变量警告几乎总是某个地方的逻辑错误,尽管 Perl 很擅长修复它。如果你得到这些,你应该寻找以下内容:

  1. 我在调用返回的东西undef吗?如果是这样,我是说错了,还是参数不好?//如果我的调用有效,我可以替换一个默认值而不会出错,比如 0 或 ''(使用定义或运算符)?我是否需要一个表格或子表格来给我默认值?如果我不能使用默认值,我的逻辑有什么问题?
  2. 如果不是这种情况,我是在引用未初始化的数组或哈希条目吗?Perl 将自动激活这些条目并将它们设置为undef. 我的索引或键是坏的吗?如果不是,我应该自己将这些条目设置为默认值,检查我的数组索引,还是检查哈希元素exists是否为哈希?否则,适用 1. 中的标准。
  3. 如果这些都不是,我有一个未初始化的标量变量。为什么没有初始化?我应该把它初始化成什么?我忘记做了什么假设(通过不将标量初始化为已知值)?

一般来说,除非您的代码应该发出警告(例如,您在其中添加了warn一个警告),否则警告意味着某些事情与您预期的不一样。您应该查看它并了解原因,而不仅仅是隐藏诊断。

于 2014-09-23T03:04:50.627 回答
0

如果您想要做的只是摆脱您已经期望并考虑的特定警告,那么您所要做的就是:

{    no warnings 'uninitialized';
     # **Small** bit of code causing the problem.
     say "A string and $probably_undefined";
}

我强调,代码的原因是 Perl 没有一千个警告类别可以通过 pragma 打开和关闭。它有几个相当广泛的类别,如果你因为太大而解除武装,那么空间咬你。这个想法是查看每个警告条件并确定未初始化的值是否无效 - 或者您至少可以解释的值。

于 2013-01-18T12:49:47.317 回答