In an overloaded assignment method like -=, it is an error for most code to take a reference to $_[0] and include it in the result. Most often, this code should copy $_[0] into a temporary variable like $self and reference that instead. The rest of this note explains the problem that occurs when you use \$_[0].

The proper way to take a reference to $_[0] and include it in your result object.

sub subtract { my $self = $_[0]; return bless [ \ $self ], "..."; }

The details

In a -= method I wanted to take a reference to the current object and incorporate it into the new value. The normal way to do this is to take a reference to it and return a new object.

sub subtract { return bless [ \ $_[0], ... ], "..."; }

My expectation is that I would get an object containing a reference to another object. That expectation was violated when I got an object with a reference to itself. Due to some magic on the part of overload or the C code in perl implementing overloading, \ $_[0] in the return value is modified into a circular or self-reference.

Expected result

$result = bless( [ \ ... ], "..." );

Actual result showing the self reference

$result = bless( [ \ $result ], "...";

The fix was to reference the $_[0] value under a different name. I opted to use normal object code and said $self = shift so $_[0] would now be in $self. After doing this, I could take references to that value without having perl modify my result into a self-reference.

To debug the original behaviour, I created my correct data structure in my subtract() method, dumped it with Data::Dump::Streamer, returned it, and then dumped it again immediately outside. The observed behaviour was some "magical" alteration was occuring to my data between the time the return() happened and the time the value appeared as a value to be assigned.

I went so far as to run this code under a debugging perl to watch all the opcodes being executed. No additional code was being run and thus no perl code had the opportunity to alter my data. I attempted to debug this under gdb but due to my lack of skill wasn't able to verify that the returned value in (SV*)res in Perl_amagic_call was as I expected it.

Note that I checked that the object I was about to return was some ARRAY(0x12345) and my returned value was also the same ARRAY(0x12345). The trouble is that the contents of the object were being mysteriously modified. It would be incorrect to think that a different object was being constructed or returned by some other unrelated code. I verified that I had the same object inside the subtract() call and outside. I verified the data structure prior to returning it and afterward. The reference to $_[0], not ARRAY(0x12345), was translated into a reference to ARRAY(0x12345)

To summarize, when writing overload functions that may be used for assignment, be sure to not write anything that includes $_[0] by reference. Always copy that out first.


In reply to A warning about overloading assignment methods by diotalevi

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.