INB4 TRWTF is PHP
-
While working on some PHP I ran into something... peculiar.
Simplified example:
<?php error_reporting(E_ALL); ini_set("display_errors", 1); $arr = array(); $arr['elems'] = array(); for($i = 0; $i < 10; ++$i) { $arr['elems']['stupid'.$i] = array(); array_push($arr['elems']['stupid'.$i], array('val' => $i)); } for($i = 0; $i < count($arr['elems']); ++$i) { $arr['elems'][$i]['val'] = $i + 1; } ?>
This code has a bug. See it? In the second
for
loop I'm trying to set the value of$arr['elems'][$i]
which doesn't actually exist: the keys are actually named$arr['elems']['stupid0 ... stupid9']
.Ok, so, what would you expect to happen here? You expect to get an error about an invalid element, right?
Guess again:
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 72 bytes) in /home/onyx/public_html/test/stupid.php on line 16
What in the actual fuck? What the hell is it even trying to do? How the hell does it result in an infinite loop? I don't even...
-
TRWTF is PHP
-
PHP creates an element if you try to assign to a key that doesn't exist. It's a handy feature.
-
Well, I guess that makes sense. Which then increases the count... fucking awesome.
Hey, you know what I should have done? Used
foreach
! That way nothing would happen because it operates on a copy of the array and my original one wouldn't be affected! Yay!
-
Oh, and the reason you get confused by the shit like this?
$arr = array(); $arr['elems'] = array(); for($i = 0; $i < 10; ++$i) { array_push($arr['elems']['stupid'.$i], array('val' => $i)); }
Warning: array_push() expects parameter 1 to be array, null given
Whoops! Now it didn't do it!
I swear, this inconsistency shit is getting me to the point where I'm forgetting things.
-
I rarely use array_push. Here's how I probably would have written the first part of your example (untested):
$arr = array(); for ($i = 0; $i < 10; $i++) $arr['elems']["stupid$i"]['val'] = $i;
although your array push is confusing me, because I feel like it would produce an array in the form:
{ 'elems': { 'stupid0': [ { 'val': 0 } ] } }
I'd need to test it to be sure, but I think you're introducing an extra array.
If you wanted that result, the initial part would look like this instead:
$arr = array(); for ($i = 0; $i < 10; $i++) $arr['elems']["stupid$i"][]['val'] = $i;
-
Yes, I needed an extra array, that was intentional.
Also, I didn't know about the [ ] syntax. Or I forgot about it. Besause
that looks terrible IMHO.
-
-
-
I have PHP Stockholm Syndrome, I admit it.
-
You should definitely work on that. That's pretty serious...
-
for($i = 0; $i < count($arr['elems']); ++$i)
$arr['elems'][$i]['val'] = $i + 1;In what language WOULDN"T that result in an infinite loop?
Since [$i]['val'] doesn't exist, you're adding 1 element to the array each time through the loop. Any language that lets you add elements to array like that will have the same problem.Pretty sure i'll have been d though
-
I think he forgot about the insanity of randomly declaring things on the fly as opposed to no such element exceptions
-
silly object oriented Array people
-
speaking of which, I unexpectedly DIDN'T get an infinite loop trying to replicate it in javascript.....
but only because adding non-numeric integer indexed items to an array doesn't count towards the length property.[code]
var a=[1];
for(var i = 0; i<a.length; i++){
a["a"+i] = 1;
}
console.log(a);
[/code]
[1,a0:1]
-
but only because adding non-numeric integer indexed items to an array doesn't count towards the length property
-
[]
is handy.
OTOH having arrays(or anything) pop of the ether has bitten me more than it helps
-
Well, you an add non-numeric properties and it doesn't count as array elements, it is a property on the object instead. To add to length you use the .push() call. Or... you can also add numeric properties on objects which JS
inconveniently will use when calculating length - except it doesn't count the # of elements, it uses the highest numeric index value (ok maybe at this point we are hitting land), so you can set[code]
var a=[1];
a[5]=1;
console.log(a.length);
console.log(a);
[/code]
[code]6
[1, 5:1][/code]so i suppose you can make a js infinite loop in a similar accidental fashion.........
[code]
var a=[1];
for(var i=0; i<a.length; i++){
a[a.length] = 5;
}
console.log(a);
[/code]don't recommend running that in your browser console though Oops.
-
I think he forgot about the insanity of randomly declaring things on the fly as opposed to no such element exceptions
Pretty much this. I'm working in 3 languages (4 if we count AEL, which is technically a configuration language) here, and PHP is the only one that does this. And it's been a long day...
-
No javascript?!
-
Oh, right, that would do it too...
I dunno man, I'm out of it today, been working for something like 12 hours at that point, my brain is fried. There's some embarrassing code I posted in another thread, you'll see...
-
There's some embarrassing code I posted in another thread, you'll see...
what has been seen can not be unseen.
unless it was in t/1000, then i forget it immediately thereafter.
what happens in t/1000 stays in t/1000.
-
That's why I posted there, yes. Softening the blow a bit
-
tbh, I didn't see the wtf, but i didn't really look all that hard.
-
Well, all the code is actually correct. But some of it is in the wrong place...
-
Example of foreach copying the array:
-
The stoned, flailing noodle arms of PHP are the reason its presence on my CV has decreased.
-
Well, all the code is actually correct. But some of it is in the wrong place...