Wie aus dieser Antwort hervorgeht , können Sie register_shutdown_function()
einen Rückruf registrieren, der überprüft wird error_get_last()
.
Sie müssen weiterhin die Ausgabe verwalten, die aus dem fehlerhaften Code generiert wurde, sei es durch den @
( Shut-Up- ) Operator oderini_set('display_errors', false)
ini_set('display_errors', false);
error_reporting(-1);
set_error_handler(function($code, $string, $file, $line){
throw new ErrorException($string, null, $code, $file, $line);
});
register_shutdown_function(function(){
$error = error_get_last();
if(null !== $error)
{
echo 'Caught at shutdown';
}
});
try
{
while(true)
{
$data .= str_repeat('#', PHP_INT_MAX);
}
}
catch(\Exception $exception)
{
echo 'Caught in try/catch';
}
Beim Ausführen wird dies ausgegeben Caught at shutdown
. Leider wird das ErrorException
Ausnahmeobjekt nicht ausgelöst, da der schwerwiegende Fehler die Skriptbeendigung auslöst und anschließend nur in der Funktion zum Herunterfahren abgefangen wird.
Sie können das $error
Array in der Funktion zum Herunterfahren auf Details zur Ursache überprüfen und entsprechend reagieren. Ein Vorschlag könnte darin bestehen, die Anfrage erneut an Ihre Webanwendung zu senden ( an einer anderen Adresse oder natürlich mit anderen Parametern ) und die erfasste Antwort zurückzugeben.
Ich empfehle jedoch, einen error_reporting()
hohen Wert-1
( Wert von ) beizubehalten und ( wie andere vorgeschlagen haben ) die Fehlerbehandlung für alles andere mit set_error_handler()
und zu verwenden ErrorException
.
Wenn Sie bei diesem Fehler Geschäftscode ausführen müssen (Protokollierung, Sicherung des Kontexts für zukünftige Debugs, E-Mail-Versand usw.), reicht die Registrierung einer Funktion zum Herunterfahren nicht aus: Sie sollten den Speicher in gewisser Weise freigeben.
Eine Lösung besteht darin, irgendwo einen Notspeicher zuzuweisen:
public function initErrorHandler() { // This storage is freed on error (case of allowed memory exhausted) $this->memory = str_repeat('*', 1024 * 1024); register_shutdown_function(function() { $this->memory = null; if ((!is_null($err = error_get_last())) && (!in_array($err['type'], array (E_NOTICE, E_WARNING)))) { // $this->emergencyMethod($err); } }); return $this; }
quelle
array (E_NOTICE, E_WARNING)
tatsächlich Abschreibungsbenachrichtigungen und andere unerwünschte kleinere Probleme erfasst. In einigen Fällen möchten Sie möglicherweise neu schreiben, um das! Negation und ersetzen Sie es durchin_array($err['type'], array (E_ERROR))
new SplFixedArray(65536);
. Jedes leere Array-Element verbraucht auf meinem System 16 Bytes.Sie können die Größe des Speichers erhalten bereits durch den Prozess verbraucht durch diese Funktion memory_get_peak_usage Dokumentationen zu verwenden sind http://www.php.net/manual/en/function.memory-get-peak-usage.php Ich denke , es würde Dies ist einfacher, wenn Sie eine Bedingung zum Umleiten oder Stoppen des Prozesses hinzufügen können, bevor das Speicherlimit durch den Prozess fast erreicht ist. :) :)
quelle
Während die @ alain-tiemblo-Lösung perfekt funktioniert, habe ich dieses Skript eingefügt, um zu zeigen, wie Sie Speicher in einem PHP-Skript außerhalb des Objektbereichs reservieren können.
Kurzfassung
// memory is an object and it is passed by reference function shutdown($memory) { // unsetting $memory does not free up memory // I also tried unsetting a global variable which did not free up the memory unset($memory->reserve); } $memory = new stdClass(); // reserve 3 mega bytes $memory->reserve = str_repeat('❤', 1024 * 1024); register_shutdown_function('shutdown', $memory);
Vollständiges Beispielskript
<?php function getMemory(){ return ((int) (memory_get_usage() / 1024)) . 'KB'; } // memory is an object and it is passed by reference function shutdown($memory) { echo 'Start Shut Down: ' . getMemory() . PHP_EOL; // unsetting $memory does not free up memory // I also tried unsetting a global variable which did not free up the memory unset($memory->reserve); echo 'End Shut Down: ' . getMemory() . PHP_EOL; } echo 'Start: ' . getMemory() . PHP_EOL; $memory = new stdClass(); // reserve 3 mega bytes $memory->reserve = str_repeat('❤', 1024 * 1024); echo 'After Reserving: ' . getMemory() . PHP_EOL; unset($memory); echo 'After Unsetting: ' . getMemory() . PHP_EOL; $memory = new stdClass(); // reserve 3 mega bytes $memory->reserve = str_repeat('❤', 1024 * 1024); echo 'After Reserving again: ' . getMemory() . PHP_EOL; // passing $memory object to shut down function register_shutdown_function('shutdown', $memory);
Und die Ausgabe wäre:
Start: 349KB After Reserving: 3426KB After Unsetting: 349KB After Reserving again: 3426KB Start Shut Down: 3420KB End Shut Down: 344KB
quelle
new SplFixedArray(65536);
. Jedes leere Array-Element verbraucht auf meinem System 16 Bytes.