Ask a Question related to PERL Miscellaneous, Design and Development.
-
valerian2@hotpop.com #1
"Undefined subroutine" error (but it's defined, I think?)
I have a program divided into 3 modules plus a main script, and some of
the modules call functions within other modules. Most of the time this
works fine, but occasionally I get an error like this:even though I made sure the caller (here Misc.pm) had imported all the> Undefined subroutine &My::Misc::DB_Disconnect called at My/Misc.pm line 18.
functions of the other module. Hence, I don't understand the reason
behind this error. I can get it to work fine by just replacing the
DB_Disconnect() call in Misc.pm with &My::Misc::DB_Disconnect(), but
that seems like a kludge, and I'd like to get a better understanding of
what's going on. :-)
Here's what happens when I run the program (under perl 5.6.1):I isolated the problem to the "use My::SOAP;" line in DB.pm, but I need> $ ./test.pl
> Error: /dev/null is full!
> Disconnecting from DB...
> Undefined subroutine &My::Misc::DB_Disconnect called at My/Misc.pm line 18.
it there because some of the DB functions operate on SOAP data. So I
left it there and poked around some more...
I then isolated the real problem to be the "use My::Misc;" line in
SOAP.pm, but again I need that line there, because the SOAP subs call
a general untainting function in Misc.pm before returning the data.
Here's the four files in question (I deleted everything but the bare
minimum to reproduce this behavior):
----- ~/test.pl ---------------------------------
#!/usr/bin/perl -w
use strict;
use My::DB;
use My::Misc;
my $dbh = DB_Connect();
SafeError($dbh, '/dev/null is full!');
----- ~/My/DB.pm --------------------------------
# Database functions
package My::DB;
use strict;
use Exporter;
use My::SOAP; # XXX this line causes the problem
use vars qw(@ISA @EXPORT);
@ISA = ('Exporter');
@EXPORT = qw(DB_Connect DB_Disconnect);
sub DB_Connect {
# stub function, always returns true
my $dbh = 1;
return ($dbh);
}
sub DB_Disconnect {
# stub function, always returns true
my ($dbh) = @_;
return (1);
}
1;
----- ~/My/Misc.pm ------------------------------
# Miscellaneous functions (error handling, logging, untainting, etc.)
package My::Misc;
use strict;
use Exporter;
use My::DB;
use vars qw(@ISA @EXPORT);
@ISA = ('Exporter');
@EXPORT = qw(SafeError);
sub SafeError {
my ($dbh, $msg) = @_;
print "Error: $msg\n";
if ($dbh) {
print "Disconnecting from DB...\n";
DB_Disconnect($dbh);
}
exit 1;
}
1;
----- ~/My/SOAP.pm ------------------------------
# SOAP functions, for exchanging data with remote site
package My::SOAP;
use strict;
use Exporter;
use My::Misc; # XXX this line causes the problem
use vars qw(@ISA @EXPORT);
@ISA = ('Exporter');
@EXPORT = qw(GetRemoteData);
sub GetRemoteData {
# stub function, always returns true
return (1);
}
1;
valerian2@hotpop.com Guest
-
Stuck email, getting error "undefined mailbox domainstring is null"
Recently there have been numerous emails in our system that are being moved to the undelivered folder. The following is the error that displays in... -
IE only "Element ... undefined in SESSION" error whencalled by Alia/Canonical Name
I repeatedly get the error "Element .. undefined in SESSION", when using IE to browse to a site using a alias/cname for the site. I've got an... -
Error "Element LOCALE is undefined in REQUEST"
Hi, Can someone help on this error: Element LOCALE is undefined in REQUEST. Thanks in advance Pandu -
(Drupal function) getting error : "notice : Undefined index ?"
hi, i have installed drupal 4.2.0 without any problems. but when i try to connect to my local webserver i get errors: "notice : Undefined... -
Error in CreatObject(""): 32797: Application-defined or object-define error
Hi, I am getting "Application-defined or object-define error" when trying to instantiate an MTS component. However, when I run the VB source-code... -
Bob Walton #2
Re: "Undefined subroutine" error (but it's defined, I think?)
[email]valerian2@hotpop.com[/email] wrote:
> I have a program divided into 3 modules plus a main script, and some of
> the modules call functions within other modules. Most of the time this
> works fine, but occasionally I get an error like this:
>> even though I made sure the caller (here Misc.pm) had imported all the>>Undefined subroutine &My::Misc::DB_Disconnect called at My/Misc.pm line 18.
>>
> functions of the other module. Hence, I don't understand the reason
No you didn't. See comments at end.
DB------------------------------------------^^^^> behind this error. I can get it to work fine by just replacing the
> DB_Disconnect() call in Misc.pm with &My::Misc::DB_Disconnect(), but
....> that seems like a kludge, and I'd like to get a better understanding of
> what's going on. :-)Note in:> ----- ~/test.pl ---------------------------------
> #!/usr/bin/perl -w
>
> use strict;
> use My::DB;
> use My::Misc;
>
> my $dbh = DB_Connect();
> SafeError($dbh, '/dev/null is full!');
>
>
> ----- ~/My/DB.pm --------------------------------
> # Database functions
> package My::DB;
>
> use strict;
> use Exporter;
> use My::SOAP; # XXX this line causes the problem
> use vars qw(@ISA @EXPORT);
> @ISA = ('Exporter');
> @EXPORT = qw(DB_Connect DB_Disconnect);
>
> sub DB_Connect {
> # stub function, always returns true
> my $dbh = 1;
> return ($dbh);
> }
>
> sub DB_Disconnect {
> # stub function, always returns true
> my ($dbh) = @_;
> return (1);
> }
>
> 1;
>
>
> ----- ~/My/Misc.pm ------------------------------
> # Miscellaneous functions (error handling, logging, untainting, etc.)
> package My::Misc;
>
> use strict;
> use Exporter;
> use My::DB;
> use vars qw(@ISA @EXPORT);
> @ISA = ('Exporter');
> @EXPORT = qw(SafeError);
>
> sub SafeError {
> my ($dbh, $msg) = @_;
>
> print "Error: $msg\n";
>
> if ($dbh) {
> print "Disconnecting from DB...\n";
> DB_Disconnect($dbh);
> }
>
> exit 1;
> }
>
> 1;
>
>
> ----- ~/My/SOAP.pm ------------------------------
> # SOAP functions, for exchanging data with remote site
> package My::SOAP;
>
> use strict;
> use Exporter;
> use My::Misc; # XXX this line causes the problem
> use vars qw(@ISA @EXPORT);
> @ISA = ('Exporter');
> @EXPORT = qw(GetRemoteData);
>
> sub GetRemoteData {
> # stub function, always returns true
> return (1);
> }
>
> 1;
>
>
perldoc -f use
that use() calls require(). Note in
perldoc -f require
that require() keeps track of which modules have been loaded in %INC (a
global variable, always in package main). Therefore, when the use()
function is called, it will do something only if that module has not
already been loaded. So each module will be loaded exactly once.
Subsequent calls to use() will not do anything. Therefore, when you use
Exporter; to export your sub's, it only happens during the first use()
of your module. Thus, the export of your sub names happens only the
first time a given modules is use()'d.
Basically, you are misusing (pun intended) the module mechanism in an
attempt to simply define subs. If all you want is for all your subs to
be present even though they are defined in other files, simply do() the
other files, and forget modules and packages. When you properly use
modules, you do not share subs (in modules, properly called methods).
From the docs for Exporter:
"Do not export method names!
Do not export anything else by default without a good reason!
Exports pollute the namespace of the module user. If you must
export try
to use @EXPORT_OK in preference to @EXPORT and avoid short or common
symbol names to reduce the risk of name clashes."
You are trying to use use() wrong. Read up on the various
object-oriented docs and buy "Object Oriented Perl" and read it.
--
Bob Walton
Bob Walton Guest
-
Abigail #3
Re: "Undefined subroutine" error (but it's defined, I think?)
Bob Walton (bwalton@rochester.rr.com) wrote on MMMDCXXX September
MCMXCIII in <URL:news:3F357BE8.1080704@rochester.rr.com>:
``
`` Note in:
``
`` perldoc -f use
``
`` that use() calls require(). Note in
``
`` perldoc -f require
``
`` that require() keeps track of which modules have been loaded in %INC (a
`` global variable, always in package main). Therefore, when the use()
`` function is called, it will do something only if that module has not
`` already been loaded. So each module will be loaded exactly once.
`` Subsequent calls to use() will not do anything. Therefore, when you use
`` Exporter; to export your sub's, it only happens during the first use()
`` of your module. Thus, the export of your sub names happens only the
`` first time a given modules is use()'d.
That's not quite true. Yes, a module is *COMPILED* only once using
this mechanism. But importing is done via the import() routine, which
is called for each time "use" appears.
If things happened as you discribe, one could use only one constant
in each program, you could use 'strict' in only one module, etc, etc.
`` Basically, you are misusing (pun intended) the module mechanism in an
`` attempt to simply define subs. If all you want is for all your subs to
`` be present even though they are defined in other files, simply do() the
`` other files, and forget modules and packages. When you properly use
`` modules, you do not share subs (in modules, properly called methods).
``
`` From the docs for Exporter:
``
`` "Do not export method names!
``
`` Do not export anything else by default without a good reason!
``
`` Exports pollute the namespace of the module user. If you must
`` export try
`` to use @EXPORT_OK in preference to @EXPORT and avoid short or common
`` symbol names to reduce the risk of name clashes."
``
`` You are trying to use use() wrong. Read up on the various
`` object-oriented docs and buy "Object Oriented Perl" and read it.
Where do object come in? The OP isn't using OO programming (and rightly so).
Abigail
--
$" = "/"; split $, => eval join "+" => 1 .. 7;
*{"@_"} = sub {foreach (sort keys %_) {print "$_ $_{$_} "}};
%{"@_"} = %_ = (Just => another => Perl => Hacker); &{%{%_}};
Abigail Guest
-
valerian@no.valid.email #4
Re: "Undefined subroutine" error (but it's defined, I think?)
In article <3F357BE8.1080704@rochester.rr.com>, Bob Walton wrote:
Alright, I went and spent some intimate time with 'man perlmod', 'man>>> even though I made sure the caller (here Misc.pm) had imported all the
>> functions of the other module. Hence, I don't understand the reason
> No you didn't. See comments at end.
perlmodlib', 'man Exporter', 'perldoc use', 'perldoc require', 'perldoc
do', and all their friends... :-)
But none of those explain why the 'use DB;' line in Misc.pm is not
importing the functions in the @EXPORT of DB.pm. The only way I can
get this to work right is either by fully qualifying the function
name (&My:DB:DB_Disconnect) or by inserting the line 'import My::DB;'
somewhere in the My::Misc::SafeError sub. But adding the import line
outside that scope doesn't work. That's what I don't understand. That
sub belongs to the My::Misc package, so why doesn't it honor the pragmas
in that package?
And to make it even more confusing, in the 'real' modules (not the
skeleton ones I listed previously) there are some subs that do honor the
package pragmas, and some that don't. In both cases I'm talking about
subs in the same package making identical calls to the same function in
another package. Frex, in My::DB, several subs call My::Misc::GetDate,
and in some cases I have to fully qualify it, and in some cases I don't.
I can't seem to find a pattern though. :-(
I rather like having everything exported as soon as possible. It's a> Note in:
>
> perldoc -f use
>
> that use() calls require(). Note in
>
> perldoc -f require
>
> that require() keeps track of which modules have been loaded in %INC (a
> global variable, always in package main). Therefore, when the use()
> function is called, it will do something only if that module has not
> already been loaded. So each module will be loaded exactly once.
> Subsequent calls to use() will not do anything. Therefore, when you use
> Exporter; to export your sub's, it only happens during the first use()
> of your module. Thus, the export of your sub names happens only the
> first time a given modules is use()'d.
mod_perl app, with all the modules preloaded by startup.pl, to avoid as
many delays as possibly...
I'm not sure what difference it makes that %INC is a global var though.
That shouldn't negatively affect My::Misc, as the 'use DB;' line would
just cause the 'require' step to be skipped and simply go on to import
the @EXPORT subs in My::DB from the copy already in memory, right?
Well I only have a rudimentary understanding of OO Perl (having read the> Basically, you are misusing (pun intended) the module mechanism in an
> attempt to simply define subs. If all you want is for all your subs to
> be present even though they are defined in other files, simply do() the
> other files, and forget modules and packages. When you properly use
> modules, you do not share subs (in modules, properly called methods).
introductory OO chapter in Advanced Perl Programming--which incidentally
I found easier to follow than the stuff in the camel book), so I'm not
quite ready to take the plunge yet. And besides, I've already got well
over 10,000 lines of procedural code that I have to finish testing ASAP,
so there's no time to start tearing things up. Maybe next project... :-)
Still, I don't think it's a total waste to use modules for just plain
old procedural code. I make judicious use of @EXPORT, @EXPORT_OK and
use specific sub names based on the package name to avoid namespace
clashes (frex, DB_Disconnect and other DB_ prefixed subs are in the
My::DB package).
valerian@no.valid.email Guest
-
Benjamin Goldberg #5
Re: "Undefined subroutine" error (but it's defined, I think?)
[email]valerian2@hotpop.com[/email] wrote:
[snip][snip function definitions]> package My::DB;
>
> use strict;
> use Exporter;
> use My::SOAP; # XXX this line causes the problem
> use vars qw(@ISA @EXPORT);
> @ISA = ('Exporter');
> @EXPORT = qw(DB_Connect DB_Disconnect);[snip function definition]> # SOAP functions, for exchanging data with remote site
> package My::SOAP;
>
> use strict;
> use Exporter;
> use My::Misc; # XXX this line causes the problem
> use vars qw(@ISA @EXPORT);
> @ISA = ('Exporter');
> @EXPORT = qw(GetRemoteData);
Remember that 'use' happens at compile time, and @EXPORT= and @ISA=
happen at run time.
If you changed the beginnings of these three modules to:
package My::DB;
BEGIN {
require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(DB_Connect DB_Disconnect);
}
use strict;
use My::SOAP;
And:
package My::SOAP;
BEGIN {
require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(GetRemoteData);
}
use strict;
use My::Misc
And:
package My::Misc;
BEGIN {
require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(SafeError);
}
use strict;
use My::DB;
Then it *should* work. [but since this code is untested, don't sue me
if it doesn't.]
--
$a=24;split//,240513;s/\B/ => /for@@=qw(ac ab bc ba cb ca
);{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "$@[$a%6
]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))&&redo;}
Benjamin Goldberg Guest
-
Bob Walton #6
Re: "Undefined subroutine" error (but it's defined, I think?)
Benjamin Goldberg wrote:
> [email]valerian2@hotpop.com[/email] wrote:
> [snip]
>> [snip function definitions]>>package My::DB;
>>
>>use strict;
>>use Exporter;
>>use My::SOAP; # XXX this line causes the problem
>>use vars qw(@ISA @EXPORT);
>>@ISA = ('Exporter');
>>@EXPORT = qw(DB_Connect DB_Disconnect);
>>
>> [snip function definition]>># SOAP functions, for exchanging data with remote site
>>package My::SOAP;
>>
>>use strict;
>>use Exporter;
>>use My::Misc; # XXX this line causes the problem
>>use vars qw(@ISA @EXPORT);
>>@ISA = ('Exporter');
>>@EXPORT = qw(GetRemoteData);
>>
>
> Remember that 'use' happens at compile time, and @EXPORT= and @ISA=
> happen at run time.
>
> If you changed the beginnings of these three modules to:
>
> package My::DB;
> BEGIN {
> require Exporter;
> @ISA = qw(Exporter);
> @EXPORT = qw(DB_Connect DB_Disconnect);
> }
> use strict;
> use My::SOAP;
>
> And:
>
> package My::SOAP;
> BEGIN {
> require Exporter;
> @ISA = qw(Exporter);
> @EXPORT = qw(GetRemoteData);
> }
> use strict;
> use My::Misc
>
> And:
>
> package My::Misc;
> BEGIN {
> require Exporter;
> @ISA = qw(Exporter);
> @EXPORT = qw(SafeError);
> }
> use strict;
> use My::DB;
>
> Then it *should* work. [but since this code is untested, don't sue me
> if it doesn't.]
Hmmmmm...yes, that does make it work. But I don't think the explanation
is quite right. @EXPORT and @ISA *do* get defined at compile time,
because the use() is the same as BEGIN{require module;import module}.
The require() do'es the module code, including the assignments to
@EXPORT and @ISA, at compile time. And the import method runs at
compile time. The do() from the use() will run before the import, so
everything should be defined. BUT some of the modules are use'd twice,
and the second time the do() is not performed. In the package of the
second call to use(), @EXPORT and @ISA don't get defined, so the routine
doesn't know it is an Exporter, so Exporter's import doesn't get called.
And the @EXPORT list doesn't get exported. Your solution works
because @ISA and @EXPORT are defined in the package namespace before the
use() is called. I think that is right because I traced through it with
the debugger with BEGIN{$DB::single=1} to debug the stuff executed at
compile time.
Pretty hairy. My apologies for my incorrect first analysis, as pointed
out by Abigail and valerian2.
--
Bob Walton
Bob Walton Guest



Reply With Quote

