Anil Kumar K K
Anil Kumar K K

Reputation: 1435

Perl : "Use of uninitialized value" though values are initialized

Perl is reporing warnings though I have properly initialized all the variables at the start. Here is my code to generate random unicast mac-address :

our $OCTATE_MAX = 255; #Max value stored in 8-bit field
our $octate1 = 0;
our $octate2 = 0;
our $octate3 = 0;
our $umac_serial = "";
sub get_umac_serial
{
    # Can not use sprintf as there is an issue with Igloo-JT
    #return "00:" . sprintf ("\00", int(rand(100))) . ":" . sprintf("\00",int(rand(100)));
     my $first = int(rand(99));
     my $second = int(rand(99));

     return "00:" . "$first" . ":" . "$second";
}
sub get_umac_address
{
    $octate1 = $octate1 + 1;
    $octate1 = int(rand(99));
    $octate2 = int(rand(99));
    $octate3 = int(rand(99));
    if ($octate1 >= $OCTATE_MAX)
    {
        $octate2 = $octate2 + 1;
        $octate1 = 0;
    }
    elsif ($octate2 >= $OCTATE_MAX)
    {
        $octate1 = 0;
        $octate2 = 0;
        $octate3 = $octate3 + 1;
    }
    elsif ($octate3 >= $OCTATE_MAX)
    {
        $umac_serial = get_umac_serial();
        print("Unicast mac-serial # $umac_serial\n");
        $octate1 = 0;
        $octate2 = 0;
        $octate3 = 0;
    }
    $umac_serial = get_umac_serial();
    #my $mac_addr = $umac_serial . ":" . sprintf("\00", $octate3) . ":" . sprintf("\00", $octate2) . ":" . sprintf("\00",$octate1);

    my $mac_addr = $umac_serial . ":" . "$octate3" . ":" . "$octate2" . ":" . "$octate1";

    print("MAC ADDR - $mac_addr\n");
    return $mac_addr;
}
return $result;
#exit;
}   ####### End of mac_addr

Though values are properly initialized, perl throws the below error :

Jul 29 01:14:25 [WARN ] perl: Use of uninitialized value in addition (+) at /var/lib/igloo_jt/explorer/2015/7/1251/mac_addr.pm line 77. Use of uninitialized value in addition (+) at /var/lib/igloo_jt/explorer/2015/7/1251/mac_addr.pm line 77. 
Jul 29 01:14:25 [WARN ] perl: Use of uninitialized value in numeric ge (>=) at /var/lib/igloo_jt/explorer/2015/7/1251/mac_addr.pm line 81. Use of uninitialized value in numeric ge (>=) at /var/lib/igloo_jt/explorer/2015/7/1251/mac_addr.pm line 81. MAC ADDR - 00:74:53:58:33:0 
Jul 29 01:14:25 [WARN ] perl: Use of uninitialized value in numeric ge (>=) at /var/lib/igloo_jt/explorer/2015/7/1251/mac_addr.pm line 81. Use of uninitialized value in numeric ge (>=) at /var/lib/igloo_jt/explorer/2015/7/1251/mac_addr.pm line 81. 
MAC ADDR - 00:51:68:64:69:0

Whats wrong with this code ?

Upvotes: 0

Views: 1075

Answers (2)

Sue D. Nymme
Sue D. Nymme

Reputation: 946

I bet that in the top of the program, the part you didn't display in your question, your main program code is calling one or more of those subroutines.

When you declare a variable with my or our, the initialization does not happen at compile-time. It only happens when normal program flow gets to the statement.

If my hunch is right, you can fix this problem by either moving the declaration to the top of your program, before any calls to functions that use the variables. Or you can write explicit compile-time initialization like this:

our $octate1;
our $octate2;
our $octate3;
BEGIN
{
    $octate1 = $octate2 = $octate3 = 0;
}

Upvotes: 1

Sobrique
Sobrique

Reputation: 53488

We can't really answer your question, because your code isn't 77 lines long. Turning on strict and warnings would help too.

However can I suggest you're doing something a lot more complicated than you need to - if you're trying to generate a random hex string mac address:

print join ( ":", map { sprintf("%02X", int (rand(  256))-1) } (0..5) );

Or as you indicate needing a 00 prefix:

print join ( ":", "00", map { sprintf("%02X", int (rand(  256))-1) } (0..4) );

I'm not sure what your issue with sprintf is - it's the tool for the job - but if that doesn't work there's other options to convert (you might have to write your own 'dectohex' function:

sub dec2hex_str {
    my ($value) = @_;
    my @conv = ( 0 .. 9, "A" .. "F" );
    my $result = '';
    while ($value) {
        my $mod = $value % 16;
        $value -= $mod;
        $value /= 16;
        $result = $conv[$mod] . $result;
    }
    if ( length($result) < 2 ) {
        $result = "0" . $result;
    }
    return $result;
}

Upvotes: 0

Related Questions