PHP looping failure when array reaches certain size - php

This has been edited a bit, sorry if any comments are out of context.
So, I'm working on the targeting challenge from gild.com. My solution concept is:
1) determine the worth of each target option (as defined by: how many options remain if it is struck)
2) slice the array at that strike point
3) drop any items with a Value lower that the last strike
4) repeat until array is empty
5) return count of strikes
Here's my latest code. I am on shared 1&1 hosting so I don't have direct access to error logs. I had a workaround in place but it's no longer writing to that file (so I'm guessing the error has changed). But when I was getting output, it was always an undefined offset...
UPDATE: now I've been playing around with echoing output from various points to see what's happening, and I found that this prevents a formal error, but it stops echoing after the depth++; loop
<?php
set_time_limit(0);
$targets=array();
$file="http://www.gild.com/coding_test_cases/missile/missile-a.in";
$input=file_get_contents($file);
$input=str_replace("\n\n","\n",$input);
$targets=explode("\n",$input);
if(strlen($targets[count($targets)-1])==0){
array_pop($targets);
}
$rich=array();
$order=array();
while(count($targets)>0){
for($i=0;$i<count($targets);$i++){
$key=$i;
$depth=0;
while($key<count($targets)){
if($targets[$key]>$targets[$i]){
$depth++;
}
$key++;
}
$rich[$i]=$depth;
echo "."; //-----------------------------------I will make it to the screen
}
echo "hi"; //--------------------------------------------------------I will not
$last_strike=$targets[array_pop(array_keys($rich,max($rich)))];
array_push($order,$last_strike);
$targets=array_slice($targets,array_pop(array_keys($rich,max($rich)))+1);
$rich=array();
$c=count($targets);
for($b=0;$b<$c;$b++){
if($targets[$b]<$last_strike){
array_splice($targets,$b,1,true);
$b--;
$c--;
}
}
}
echo count($order)."\n";
?>

Maybe I'm missing something but isn't your entire code snippet equivalent to this?
$rich = range($_GET['lim'] - 1, 0);
echo $rich[0];
As for your actual error, it sounds like a memory allocation problem. Try rethinking your algorithm for this problem.

I think reason that you have 500 error instead of Human-readable error is switched off dislay_errors ini setting.
Try to switch on it or find error message in your Apache error log

Related

PHP 7 error 500 internal

I'm completely lost with an "500 internal server error".
Yesterday I updated to PHP 7.1.2 and then there were a lot of errors.
I solved them almost all except for this strange coding error.
When trying to find the problem I echoed some output to the screen.
And this is what happens:
for($iRecordNumber=0;$iRecordNumber==$iTotalAssignments;$iRecordNumber++){
$iNextRecordNumber = $iRecordNumber+1;
echo $iNextRecordNumber;
echo $aAssignments[$iRecordNumber][2];
echo $aAssignments[$iNextRecordNumber][2];
}
With this code I get the "500-error".
When I comment out the line with echo $aAssignments[$iNextRecordNumber][2]; the error is gone and it does what it should do. Showing me a record from the nested array $aAssignments(PDO query).
for($iRecordNumber=0;$iRecordNumber==$iTotalAssignments;$iRecordNumber++){
$iNextRecordNumber = $iRecordNumber+1;
echo $iNextRecordNumber;
echo $aAssignments[$iRecordNumber][2];
// echo $aAssignments[$iNextRecordNumber][2];
}
I looked through the Backward compatabilty list but did not find anything.
And the tool codechecker says it's good too.
I dont know how this is possible.
What can I do to find an answer? Are there any programs or code checkers to check for more php 7 errors in my code. I have several php sites running and I do not want to check all code manually for errors.
I think $aAssignments[$iNextRecordNumber][2] is not always set.
You could replace:
echo $aAssignments[$iNextRecordNumber][2];
By:
echo $aAssignments[$iNextRecordNumber][2]?? '';
I hope it could help.
In PHP 7 is the error handling completly revised. A fatal error other errors no longer stops the script. To find these kind of errors, use the new error() method in the try and catch class. For example:
try{
code to test on errors
} catch(error $eCatchedError) {
echo get_class($eCatchedError)."<br>".$eCatchedError->getLine()."<br>".$eCatchedError->getFile()."<br>".$eCatchedError->getMessage();
} // End try and catch
By this way you get an more elegant way of showing an error (with css and everything)

How to handle errors for debug purposes on PHP? (public strings?)

What I want to do is when an if condition doesn't go as it should, instead of echo'ing the my custom error message in else { }, storing the error message somewhere else and retrieving it from another page.
For example, this is my page with the if condition:
if ($something < 4){
echo 'yes it is less than four';
else { echo 'no it isn\'t less than four';}
I want to for example store these error messages in strings and give them numbers:
if ($something < 4){
$debug11 = 'yes it is less than four';
echo '11';
else { $debug10 = 'no it isn\'t less than four'; echo '10'; }
then let's assume there's a debug.php file with php class that can echo these messages but in order to do so it needs to know what $debug11 is, can it do that without including that php page? is that what public strings are for? or should I just define all of them in debug.php
the point of all this is that jquery will call this file.php and get a message like 11 or 10 which in this case is success or failure then I will be able to know why it failed with debug.php. numbers are easier since I may play with text messages a lot and easier to confirm with numbers than text in if conditions.
You want to store error-messages and read this messages by another script.
It means you need a storage.
As a storage, you can use files, or memcache, or APC, or queues.
Create logger, which will write messages to the storage, and then in debug.php you will read list of messages from the storage.
I recommend to use Memcache, set_error_handler and trigger_error.
I'm not sure what you mean by 'public strings', but if you are looking at accessing a variable between 2 pages, you would need to persist them into a session variable at least.
Also you might be better off using PHP assertions to check for error conditions within your code (I think that's what your trying to achieve here):
Assertions should be used as a debugging feature only. You may use them for sanity-checks that test for conditions that should always be TRUE and that indicate some programming errors if not or to check for the presence of certain features like extension functions or certain system limits and features.
Try logging to file: http://nl3.php.net/manual/en/errorfunc.configuration.php#ini.error-log. You can supply a custom log file in which you can find all your errors.
If you put in a error handler you should be able to create debug messages and store them in another file.
Write own logging mechanism and put log messages in a file.
As above I am not 100% sure what you are trying to do, however instead of using variables for your custom error messages it may be better to use Constants. The benefits of them are that the values can't be rewritten unlike your variable where you can change the value within your script.
Your code would look something like this:
define("ERROR1", "It wont Work!");
define("ERROR2", "It still wont Work!");
define("ERROR3", "It must be broken!");
if ($something < 4){
echo '11';
} else {
echo ERROR1; // Prints "It wont Work!"
}
You can store these Constants in your debug.php file and use them on any page you include the file on.
Hope this helps.

How to make PHP undefined constants notice an error

I just spent hours trying to debug an out of memory error caused by the following code:
for ($i = 1; i <= 4; $i++) {
$allowed[] = $type.'_'.$i;
}
Which PHP kindly mangles into:
for ($i = 1; 'i' <= 4; $i++) {
$allowed[] = $type.'_'.$i;
}
This causes an endless loop, which eventually leads to an out of memory error due to appending to the array. PHP will generate a notice level error, and I could change my error reporting level to show these but I am working on a third party application which has a tendency to generate enough of these that this isn't really a viable solution.
Is there any way to trap these really simple bugs? Ironically, if you do something like constant('i') and explicitly ask for the value it will generate a warning rather than a notice, and this behaviour would be ideal.
You could create a custom error function then filter out the most common errors and only report the less common ones. Then up the error reporting level in PHP. E.g.
function customError($error_no, $error_message, $error_file, $error_line, $error_context) {
$common_errors = Array('File not found', 'Another made up error', 'Its late');
if (! in_array($error_message, $common_errors)) {
// throw exception, log to file, or other action
}
}
set_error_handler("customError");
You could also filter errors like so:
Filter out all errors unless they are
in a file of interest by testing
$error_file against an array of
files you maintain
Even better (not on a production
server) fetch the last_modified
date/time of $error_file with
filemtime() and report the error if
it was changed within the last 10
minutes. This helps you debug code as
you write it
Or if it's within a framework which
yours sounds like it is, break apart
the path of $error_file and test if
it's in your module/view/controller
files, as opposed to core framework
files
In PHP 7.2 this notice has been changed to a warning.
In PHP 8.0 it will be an error.

PHP turn off errors - in one file only

I am well aware about error_reporting(0); & ini_set('display_errors', "Off"); to make error messages go away.
What would be an appropriate way to do this - for a specific file or part of code only?
Surpressing errors with #'s seems like a bad idea since it apparently slows the code down...
The reason? We have a number of memcached servers in a development LAN that is really unreliable due to the network settings, thereby we are recieving errors multiple times every hour and there's nothing we can do about it except stop using memcache or turning off errors for the whole application, which would be giving us a headache - in the middle of the development stage :)
<?php
// normal code
// error_reporting returns the old error code
$old_error_reporting = error_reporting(0);
// your errorful code
// reset error_reporting to its old value
error_reporting($old_error_reporting);
// normal code
Although it would be a good idea to fix what is actually causing the errors.
You've kind of answered your own question. To do it for a specific file, error_reporting(0); will turn off errors. You can also call it multiple times in a script, I think.
You can also use php exceptions to 'catch' errors over a block of code. For example:
try {
// code to ignore errors for here
} catch {
// you can output a custom error here, but putting nothing here will effectively mean errors are ignored for the try block
}
The script will continue running past the try block, even if there is an error within it. See the PHP Manual Entry for more information.
You can change the error reporting level during runtime:
<?
error_reporting(E_ALL);
... some code ....
error_reporting(0);
... some more code ....
error_reporting(E_ALL);
I know of no other way but I can't think of a case where this wouldn't be sufficient. Can you?
That's really a long time ago but someone like me would maybe use my answer.
When i need to do this kind of stuff, i just put # before the variable in order to NOT display the errors coming from this variable.
example:
switch(#$var!="e") {
....
}

EINTR error for semop call

I am using the following code fragment in a php script to safely update a shared resource.
$lock_id = sem_get( ftok( 'tmp/this.lock', 'r'));
sem_acquire($lock_id)
//do something
sem_release($lock_id)
When I stress test this code with large number of requests I get an error:
Warning: semop() failed acquiring SYSVSEM_SETVAL for key 0x1e: No space left on device in blahblah.php on line 1293
php sources show the following code for failed acquiring SYSVSEM_SETVAL
while (semop(semid, sop, 3) == -1) {
if (errno != EINTR) {
php3_error(E_WARNING, "semop() failed acquiring SYSVSEM_SETVAL for key 0x%x: %s", key, strerror(errno));
break;
}
}
which means semop fails with EINTR. man page reveals that the semop() system call was interrupted by a signal.
My question is can I safely ignore this error and retry sem_acquire?
Edit: I have misunderstood this problem, Pl see the clarification I have posted below.
raj
I wouldn't ignore the ENOSPC (you're getting something other than EINTR, as the code shows). You may end up in a busy loop waiting for a resource that you have earlier exhausted. If you're out of some space somewhere, you want to make sure that you deal with that issue. ENOSPC generally means you are out of...something.
A couple of random ideas:
I am not an expert on the PHP implementation, but I'd try to avoid calling sem_get() each time you want the semaphore. Store the handle instead. It may be that some resource is associated with each call to sem_get, and that is where you're running out of space.
I'd make sure to check your error returns on sem_get(). It's a code snippet, but if you were to fail to get the sema4, you would get inconsistent results when trying to sem_op() it (perhaps EINTR makes sense)
After posting this question I noticed that I misread the code as errno == EINTR and jumped into conclusion. So as bog has pointed out, the error is ENOSPC and not EINTR. After some digging I located the reason for ENOSPC. The number of undo buffers were getting exhausted. I have increased the number of semmnu and now the code is running with out issues. I have used semmni*semmsl as the value of semmnu

Categories