This is a bug in Perl. As a work-round use exists() rather than defined().
It has something to do with a bit of DWIMery what happens if you take a reference to function that has not yet been defined. This DWIMery exists so that you can export autoloaded functions.
sub one { 'one' };
sub foo { 'zero' };
my $bar = \&foo;
print \&foo,$bar; # Prints the same thing twice
*foo = \&one; # Emits redefined warning
print $bar->(); # Prints zero
print \&foo,$bar; # Prints different things
eval "sub foo { 'two' }"; # Emits redefined warning
print $bar->(); # Still prints zero
print 0+defined(&$bar); # Prints 1
All that seems in line with how one expects hard code references to behave.
sub one { 'one' };
my $bar = \&foo; # &foo does not yet exist
print \&foo,$bar; # Prints the same thing twice
*foo = \&one;
print \&foo,$bar; # Prints different things
print $bar->(); # Prints one
eval "sub foo { 'two' }"; # Emits redefined warning
print $bar->(); # Prints two
The supposedly hard code reference $bar is actually
behaving as if it were a symbolic reference to
&main::foo.
However in this case...
print 0+defined(&$bar); # Prints 0
...and this as I said before, IMNSHO, is a bug in Perl. It should print 1.