in reply to Re^2: "Attempt to free unreferenced scalar" and "Scalars leaked: 1" ?
in thread "Attempt to free unreferenced scalar" and "Scalars leaked: 1" ?

There are so many problems with your test code that you are almost certainly not testing the code you think you are. See the comments below:

package test; require Exporter; our @ISA =qw(Exporter); our @EXPORT =qw(queuereader); ## You are exporting "queuereader" our @VERSION =1.0; sub forthread{ ## Not the forthread function that is in the f +ile! my ($arg)=@_; return 0; } #forthread ## You have no module termination value, 1;

All of which leads me to believe that you aren't actually running this module when you run test.pl. Instead you are probably picking up another module called test from somewhere else.

Now to test.pl

use threads; use test; my $argument=1; ## VVVVVVVVVV---- this is not a function refe +rence, its a string! my $thread=threads->create("forthread", ($argument)); $thread->join(); exit(0);

If I attempt to run this pair of files:

## test.pl use threads; use Testit; my $argument=1; my $thread=threads->create( 'forthread', ($argument)); $thread->join(); exit(0); ## Testit.pm package Testit; require Exporter; our @ISA =qw(Exporter); our @EXPORT =qw(forthread); our @VERSION =1.0; sub forthread{ my ($arg)=@_; warn "$arg"; return 0; } 1;

I get the following output:

C:\test>test.pl 1 at Testit.pm line 11. Attempt to free unreferenced scalar: SV 0x194aa50, Perl interpreter: 0 +x18290c4 during global destruction.

Which shows that the function forthread has been exported from the package Testit into main, and has been run as a thread, but when the cleanup of the thread happens, it detects a leaked scalar--the string you passed.

However, if I modify test.pl to pass a coderef rather than a string to the thread creation

use threads; use Testit; my $argument=1; my $thread=threads->create( \&forthread, ($argument)); $thread->join(); exit(0); __END__ C:\test>test.pl 1 at Testit.pm line 11.

I get no error. There are two ways of looking at this. The ability to pass a subroutine name as a string (and possibly a bareword if not using strict?) is a throwback to earlier time (perl 4?), but the code underlying the autoresolution of a string to a coderef is still embedded in the API code. However, newer modules and features may have been written by authors who never used this feature, and so their code does not cater for it.

Specifically, the string containing the function name is duplicated as a string for use on the thread that will be created, but because the author(s) of the threads module where expecting a coderef, they do not deal with this situation. So the other way of looking at it is that this is a bug in the threads module somewhere.

The simplest way of avoiding it is to pass a coderef in the first place.

And when you post demo code, it would be nice if it actually worked to demonstrate the problem described :) test.pm is a bad choice of module/package name.


Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
"Too many [] have been sedated by an oppressive environment of political correctness and risk aversion."

Replies are listed 'Best First'.
Re^4: "Attempt to free unreferenced scalar" and "Scalars leaked: 1" ?
by licht (Novice) on Apr 01, 2007 at 08:28 UTC

    Thanks a lot! BrowserUk. You are really great!

    I'm sorry in fact there are some typos such as exported function names and missing the "1;" at the end of test.pm, etc. I should've double check my post...

    But I am really weak on this part. The syntax to specify the subroutine-name in threads->create is confusing to me. And I guess maybe the latest release has addressed this problem (passing subroutine-name as string instead of code-ref). I have another question about code ref. In fact, I want my code to deal with unknown subroutine name beforehand. Instead, the name may be given in a parameter file in XML like the following:

    <thread> <module>module_name</module> <subroutine>subroutine_name</subroutine> </thread>

    A script reads the file and put modulename in var "$module" and subroutinename in "$subroutine". Then, what is the correct syntax to create a thread for "$subroutine"? I guess I have to use Module::Load to dynamically load a module first and then call threads->create to run a thread for a subroutine. Will this cause some problem?


    Thanks!

    And I rewrite 2nd part as follows. Please help. Thanks!


    "Scalar leaked:1" error.
    It is for simplicity that bareword "argument" is used in place of any type of variable.
    _test.pl_
    use threads; use test; my $thread=threads->create('forthread', (argument)); $thread->join(); exit(0);

    -test.pm_
    package test; require Exporter; our @ISA =qw(Exporter); our @EXPORT =qw(forthread); our @VERSION =1.0; sub forthread{ my (argument)=@_; my $thread=threads->create('another', (argument)); $thread->join(); return 0; } #forthread sub another{ return 0; } #another

    NOTE: the error is reported when "argument" is one of the following:
    - reference to scalar
    - reference to array
    - reference to hash
    - hash

      With a Testit.pm that looks like this:

      package Testit; require Exporter; our @ISA = qw[ Exporter ]; our @EXPORT = qw[ forthread ]; our @VERSION = 1.0; sub forthread{ my ($arg)=@_; warn "forthread called with argument: '$arg'"; return 0; } 1;

      And a test.pl that looks like this:

      #! perl -w use strict; use threads; use XML::Simple; use Data::Dumper; my $data = ' <cde> <thread> <module>Testit</module> <subroutine>forthread</subroutine> </thread> </cde> '; my $ref = XMLin( $data ); print Dumper $ref; my $argument=1; require $ref->{thread}{module} . '.pm'; ## Line A my $thread=threads->create( \&{ $ref->{thread}{module} . '::' . $ref->{thread}{subroutine} }, +# Line B $argument ); $thread->join(); exit(0);

      I get the following output:

      c:\test>test $VAR1 = { 'thread' => { 'subroutine' => 'forthread', 'module' => 'Testit' } }; forthread called with argument: '1' at Testit.pm line 11.

      The salient parts of this are lines A & B

      1. require $ref->{thread}{module} . '.pm';

        This concatenates the module name from the XML with '.pm' and then requires the module.

        Omitting the '.pm' from the XML simplifies the next line, but you could include it if it was important. You'd just have to strip it away for the next bit.

      2. \&{ $ref->{thread}{module} . '::' . $ref->{thread}{subroutine} },

        This builds a string from the module name and subroutine name:

        $ref->{thread}{module} . '::' . $ref->{thread}{subroutine}

        Note: It means you don't have to export the function from the module, thereby avoiding polluting your main, and the risk of conflicts where two more modules export the same subroutine.

        It then asks Perl to treat that string as the name of a subroutine by placing it inside &( ... }:

        &{ 'Testit::forthread' }

        And finally (and subtly), it asks for a reference to that subroutine

        \ &{ 'Testit::forthread' }

        Without the \, the &{ 'subroutine' } construct would immediately call the subroutine named, and it would be the return value from the subroutine that would be passed to threads->create(). Which wouldn't do at all. The backslash tells perl to not invoke the subroutine, but rather return a coderef to instead.

      Interestingly, if you wanted to invoke the subroutine via the &{ ... } construct, and are useing strict, then you would have to disable strict for this with no strict 'refs';, as this is a symbolic reference. However, by asking for a coderef, it appears to bypass the strict detection mechanisms and lets you get away without disabling strict. I only discovered this because I reused your early code which didn't have strict enabled.

      You might want to add the no strict 'refs'; anyway, as it would act as a warning/reminder that something unusual is going on here. Eg.

      require $ref->{thread}{module} . '.pm'; my $thread=threads->create( do{ no strict 'refs'; \ &{ $ref->{thread}{module} . '::' . $ref->{thread}{subroutine} } }, $argument );

      Here the do{ .. } block serves to confine the effects of the no strict 'refs' to exactly that piece of code where it is(n't :) needed.

      You could of course, assign the concatenated name to a variable and the substitute that variable for the string:

      require $ref->{thread}{module} . '.pm'; my $subname = $ref->{thread}{module} . '::' . $ref->{thread}{subroutin +e}; my $thread=threads->create( do{ no strict 'refs'; \ &{ $subname } }, $argument );

      if you feel that clarifies things. Many here would, and looking again at the above, in this case I might agree with them.


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.

        Wow, you must be a GURU:)
        I really learned a lot! THANKS A MILLINION!

        Another thing just came to my mind, it makes more sense to give PATH to module. So, we will have a PATH/modulename. "require" can handle a path, right? what about Module::Load, it seems to me there's ssome difference but not very clear ... Thanks!