http://www.perlmonks.org?node_id=1200833

cgoolsby has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks, This question is more of a interesting concern. I have some modularized code. In this code, I pass an array reference to a function which returns a different array as a reference. i.e.:
use ModuleName qw(moduleFunction); @arrayPassedIn = qw(some values here); #there are 9 values, to be specific. $return = moduleFunction(\@arrayPassedIn); @arrayToPrint = @$return;
For reference to module function looks like:
sub moduleFunction{ $input = shift; @arrayToBeManipulated = @$input; #manipulations occur here producing a new array with 6 values; @newArray = qw(6 unique values); return \@newArray; }
So here is the kicker. When I print @arrayToPrint, I get the 6 values that I desire, and then the last 3 values of the array I passed into my function. Is this as intended? Am I doing something wrong? It doesn't effect my code, because I just discard these values, but I am curious what is going on.
Cheerfully,
C
P.S. this is my first post on here. If I am violating any rules, I apologize in advance. Also, if you see a simple way I can improve my conventions for coding, I am largely self-taught and happy to learn and improve!

Replies are listed 'Best First'.
Re: Leaking Function Return
by haukex (Archbishop) on Oct 06, 2017 at 15:15 UTC
    this is my first post on here. If I am violating any rules, I apologize in advance. Also, if you see a simple way I can improve my conventions for coding

    Welcome, and no worries, for a first post it's fine :-) Some good introductory reading is PerlMonks for the Absolute Beginner, The Perl Monks Guide to the Monastery, and How do I post a question effectively?

    Sorry, I can't reproduce the issue, neither with your original code with strict turned off, or with it turned on and the appropriate my declarations added (although I'm not surprised by the latter). Without seeing more code (a representative Short, Self-Contained, Correct Example), I can only guess: Either you're making a mistake somewhere in the "manipulations occur here producing a new array with 6 values", which you haven't shown us, or, since you're apparently not using strict, meaning all of those variables are global, there is some "cross-contamination" happening between the arrays (Update 2: I just wrote some more on that here). This is one reason you should always Use strict and warnings*, since it helps enforce proper scoping of your variables!

    * Update: Your program should begin with this, see the Basic debugging checklist:

    use strict; use warnings; use diagnostics;
Re: Leaking Function Return
by Laurent_R (Canon) on Oct 06, 2017 at 15:22 UTC
    I do not see anything in the code you posted that should lead to the subroutine input parameters to be inserted into @arrayToPrint. So, assuming I did not miss something (as I can't test your code right now), the problem must be in the code that you haven't shown.

    As for coding improvement, yes, there are a few thing you could do. The main one, though, is to have these two pragmas:

    use strict; use warnings;
    near the top of each of your programs and to declare your variables with the my keyword.
      Thank you all for your help. It appears that I had some kind of global variable problem. Switching to:
      use strict; use warnings;
      has made the 'leak' disappear. I will make sure to apply this wisdom in the future.
      Cheerfully,
      C

        Just to explain one possibility of what might be going wrong in your original code without strict, so that it doesn't remain a mysterious "leak", because this kind of thing can theoretically bite you even under strict (although it's a lot less likely):

        When you don't use strict, all the variables you use without a declaration are automatically "package variables", that is, they are global everywhere in their package, and since most scripts only have one package (the default, main), they're effectively global throughout the entire script. So anywhere you take a reference to an array that is a package variable (\@newArray), that's always going to refer to the same array (Update: I'm simplifying a bit and leaving out some "advanced" stuff like local for the sake of this explanation). So if you make modifications to that array anywhere in the script, they will be visible everywhere else. This may be what is biting you in your original code.

        So when you do use strict, you're forced to declare all your variables e.g. with my or our. The latter actually declares package variables, so they'll have the same behavior as I just described. But variables declared with my are "private" to the enclosing block, meaning that code outside the block can't normally see or access them. Every time you call a subroutine that contains a my @newArray declaration, that will create a new memory location for you - this is the important part in this case. Every time you run that sub and do return \@newArray, that's a new array. (More details in Private Variables via my().)

        Here's a demo, two functions that re-implement Perl's x operator for lists, one correctly and one incorrectly:

        use warnings; use strict; use Data::Dump; sub good { my ($string,$times) = @_; my @array; # lexical variable push @array, $string for 1..$times; return \@array; } sub bad { my ($string,$times) = @_; our @array; # package variable # always the same "@array" here! push @array, $string for 1..$times; return \@array; } my $arr1 = good("foo",2); dd $arr1; # prints ["foo", "foo"] my $arr2 = good("bar",2); dd $arr2; # prints ["bar", "bar"] my $arr3 = bad("quz",2); dd $arr3; # prints ["quz", "quz"] my $arr4 = bad("baz",2); dd $arr4; # prints ["quz", "quz", "baz", "baz"]

        Of course, it could also be something a bit simpler, like that you accidentally re-used variable names like @newArray or @arrayToBeManipulated in multiple places in your code.

Re: Leaking Function Return
by 1nickt (Canon) on Oct 06, 2017 at 15:11 UTC

    Welcome to the Monastery. It's a well-formed question, except: you would have to post the actual code from your sub that "manipulates" the array, since it is clearly not doing what you think, and we can't help you fix it if we can't see it.


    The way forward always starts with a minimal test.