return by reference behaviors in PHP 5

php.internals

Daniel Convissor

22 years ago
Greetings: I'm familliar with the new "Only variables or references can be returned by reference" behavior in PHP 5 and am helping the PEAR crew resolve compatibility issues on this front. I ran some tests using the php5-win32-200311111530 snapshot and came across results I didn't expect. I thought PHP 5 was only supposed to return variables. But it just as happy to return strings, expressions, constants, etc. Conversely, attempts to return a variable on the line of the return doesn't fly. Is all of this intended? Will any of these behaviors cause memory corruption? Will these behaviors change? It seemed better to ask now both to make sure this is what's supposed to happen and to ensure PEAR developers don't have to do yet another code rewrite later. I searched various list and news group archives for answers to this, but found nothing exactly covering this matter. Below is a test script outlining what happened vs what I thought would happen. Thanks, --Dan function &intention() { $x = 1; return $x; // works, as intended } define('DB_OK', 'a constant'); function &a_const() { return DB_OK; // works, but should it? } function &str() { return 'a string'; // works, but should it? } function &int() { return 4; // works, but should it? } function &tru() { return true; // works, but should it? } function &nul() { return null; // works, but should it? } function &expr() { return 5 + 2; // works, but should it? } function &assign() { return $x = 8; // error, but shouldn't it return $x by reference? } $y =& intention(); echo "<br />intention() = $y"; $y =& a_const(); echo "<br />a_const() = $y"; $y =& str(); echo "<br />str() = $y"; $y =& int(); echo "<br />int() = $y"; $y =& tru(); echo "<br />tru() = $y"; $y =& nul(); echo "<br />nul() = $y"; $y =& expr(); echo "<br />expr() = $y"; $y =& assign(); echo "<br />assign() = $y"; /* * RESULTS * * intention() = 1 * a_const() = a constant * str() = a string * int() = 4 * tru() = 1 * nul() = * expr() = 7 * * Fatal error: Only variables or references can be returned by reference * in d:\atest.html on line 36 */
-- T H E A N A L Y S I S A N D S O L U T I O N S C O M P A N Y data intensive web and database programming http://www.AnalysisAndSolutions.com/ 4015 7th Ave #4, Brooklyn NY 11232 v: 718-854-0335 f: 718-854-0409

Daniel Convissor

22 years ago
Hi Folks: I'm sorry to be a nudge, but am surprised no one has replied to my prior post. Perhaps someone is doing some testing or research before replying? Perhaps it got overlooked? Perhaps everyone is busy and thought someone else would answer? Regardless, it would be great if someone could reply. Thanks, --Dan Message-ID: <20031112174553.GA23321@panix.com> Archive URI: http://marc.theaimsgroup.com/?l=php-dev&m=106866036715442
-- FREE scripts that make web and database programming easier http://www.analysisandsolutions.com/software/ T H E A N A L Y S I S A N D S O L U T I O N S C O M P A N Y 4015 7th Ave #4AJ, Brooklyn NY v: 718-854-0335 f: 718-854-0409

Andi Gutmans

22 years ago
I'll try and take a look at it next week (I had no time this week). The problem is that there where bugs in the past when returning by reference not variables, which could cause memory corruptions. This is why we didn't allow it. In order not to completely break every script in some cases we can turn a blind eye and allow it (such as return 4;) because it can be dealt with. Anyway, as I said it's something I need to look into more detail again which I'll do soon. Andi At 01:39 PM 11/14/2003 -0500, Daniel Convissor wrote:

Daniel Convissor

22 years ago
Hi Andi: On Fri, Nov 14, 2003 at 10:24:45PM +0200, Andi Gutmans wrote:
> I'll try and take a look at it next week (I had no time this week).
Understandable. Thanks for the update.
> The problem is that there where bugs in the past when returning by > reference not variables, which could cause memory corruptions.
Yes, yes.
> In order not to completely break every script in some > cases we can turn a blind eye and allow it (such as return 4;) because it > can be dealt with.
I assume by something along the lines of internally assigning it to a variable with a pointer to it (pardon the potential lack of computer science / C programming terminology). I guess, then this begs the already answered question -- why not do the same with methods, etc? The answer thus far has been that it's too hard to do, which is okay by me.
> Anyway, as I said it's something I need to look into more detail again > which I'll do soon.
Just to clarify, my main concern is that everyone know what the behavior is going to be and that it's not going to change again, then document the precise rules. I'll be glad to help with documentation, when it comes to that point. Though, it seems the behavior should be consistent -- sometimes I'm too logical :) -- so returning a variable is okay and the rest of it should be blocked, OR rework the system so anything can be returend. Thanks again, --Dan
-- FREE scripts that make web and database programming easier http://www.analysisandsolutions.com/software/ T H E A N A L Y S I S A N D S O L U T I O N S C O M P A N Y 4015 7th Ave #4AJ, Brooklyn NY v: 718-854-0335 f: 718-854-0409

Daniel Convissor

22 years ago
Hello Again: Pardon the followup to myself... On Fri, Nov 14, 2003 at 05:51:12PM -0500, Daniel Convissor wrote:
> Though, it seems the behavior should be consistent -- sometimes I'm too > logical :) -- so returning a variable is okay and the rest of it should be > blocked, OR rework the system so anything can be returend.
I did some more testing on this front and ran into some VERY weird behavior which seems to reinforce the point I made above. The test script is below by sig. Thanks, --Dan
-- FREE scripts that make web and database programming easier http://www.analysisandsolutions.com/software/ T H E A N A L Y S I S A N D S O L U T I O N S C O M P A N Y 4015 7th Ave #4AJ, Brooklyn NY v: 718-854-0335 f: 718-854-0409 <?php /* * Is this an example of memory corruption due to attempting to * return by reference on non-variables? * * BASE OUTPUT: * Ref 1 * RefAdd st 10-21-03 06:01 et * * BUT, the output changes dramatically depending on which lines * are commented and uncommented. Read the block comments below * for more information. * * PLATFORM: * Windows 2000 * PHP 5.0.0b3-dev (cgi-fcgi) (built: Nov 11 2003 16:10:23) * Apache 1.3.28 */ class x { var $int = 1; function x() { $this->Data['DATETIME'] = 'st 10-21-03 06:01 et'; /* * Commenting out next three lines changes output to: * Ref 1 * Fatal error: Cannot return overloaded elements or * string offsets by reference... line 43. */ if ( preg_match('/st (\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d) et/i', $this->Data['DATETIME'], $Atom) ) { } } function &Ref() { return $this->int; } function &RefAdd() { return ++$this->int; // Line 43 } function Not() { return $this->int; } } $y = new x; /* * Uncommenting the next two lines changes the output to: * Fatal error: Only variables or references can be returned * by reference... line 43 */ // $a =& $y->RefAdd(); // echo "<br />RefAdd $a"; $b =& $y->Ref(); echo "<br />Ref $b"; /* * Uncommenting the next two lines changes the output to: * Ref 1 * Not 1 * RefAdd 2 */ // $c = $y->Not(); // echo "<br />Not $c"; $d =& $y->RefAdd(); echo "<br />RefAdd $d"; ?>