Ik heb een stel klantpunt van verkoop (POS) -systemen die periodiek nieuwe verkoopgegevens verzenden naar een gecentraliseerde database, die de gegevens opslaat in één grote database voor rapportgeneratie.
De client POS is gebaseerd op PHPPOS, en ik heb een module geïmplementeerd die de standaard XML-RPC-bibliotheek gebruikt om verkoopgegevens naar de service te verzenden. Het serversysteem is gebouwd op CECENTONTICTER en gebruikt de XML-RPC- en XML-RPCS-bibliotheken voor de WebService-component. Wanneer ik veel verkoopgegevens verzenden (zo weinig als 50 rijen van de verkooptabel en individuele rijen van sales_items met betrekking tot elk item binnen de verkoop) krijg ik de volgende fout:
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 54 bytes)
128M is de standaardwaarde in PHP.ini
, maar ik neem aan dat het een enorm aantal is om te breken. In feite heb ik zelfs geprobeerd deze waarde te plaatsen tot 1024m, en alles wat het doet is een langere tijd om eruit te fouten.
Wat betreft stappen die ik heb ondernomen, heb ik geprobeerd alle verwerking aan de serverzijde uit te schakelen en hebben ze opgetuigd om een ingeblikte reactie terug te sturen, ongeacht de invoer. Ik geloof echter dat het probleem ligt in de daadwerkelijke verzending van de gegevens. Ik heb zelfs geprobeerd de maximale uitvoeringstijd van het script voor PHP uit te schakelen en het fouten eruit.
1, Autoriteit 100%
Wijzig de memory_limit
door ini_set('memory_limit', '-1');
is niet een goede oplossing. Doe dat alsjeblieft niet.
Je PHP-code kan ergens een geheugenlek hebben en je vertelt de server om gewoon al het geheugen te gebruiken dat hij wil. Je zou het probleem helemaal niet hebben opgelost. Als u uw server in de gaten houdt, zult u zien dat deze nu waarschijnlijk het grootste deel van het RAM-geheugen gebruikt en zelfs naar schijf overschakelt.
U moet waarschijnlijk proberen de aanstootgevende code in uw code op te sporen en te repareren.
Antwoord 2, autoriteit 28%
ini_set('memory_limit', '-1');
overschrijft de standaard PHP-geheugenlimiet.
Antwoord 3, autoriteit 19%
De juiste manier is om je PHP.ini
-bestand te bewerken.
Bewerk memory_limit
naar uw gewenste waarde.
Vanaf uw vraag is 128M
(wat de standaardlimiet is) overschreden, dus er is iets ernstig mis met uw code omdat er niet zo veel voor nodig is.
Als je weet waarom het zoveel kost en je wilt het toestaan, stel dan memory_limit = 512M
of hoger in en je zou goed moeten zijn.
Antwoord 4, autoriteit 14%
De geheugentoewijzing voor PHP kan permanent of tijdelijk worden aangepast.
Permanent
Je kunt de PHP-geheugentoewijzing op twee manieren permanent wijzigen.
Als je toegang hebt tot je PHP.ini
-bestand, kun je de waarde voor memory_limit
aanpassen aan je gewenste waarde.
Als u geen toegang heeft tot uw PHP.ini
-bestand (en uw webhost dit toestaat), kunt u de geheugentoewijzing overschrijven via uw .htaccess
-bestand. Voeg php_value memory_limit 128M
toe (of wat je gewenste toewijzing ook is).
Tijdelijk
Je kunt de geheugentoewijzing direct aanpassen vanuit een PHP-bestand. Je hebt gewoon de code ini_set('memory_limit', '128M');
(of wat je gewenste toewijzing ook is). U kunt de geheugenlimiet verwijderen (hoewel machine- of instantielimieten nog steeds van toepassing kunnen zijn) door de waarde in te stellen op “-1”.
Antwoord 5, autoriteit 8%
Het is heel gemakkelijk om geheugenlekken in een PHP-script te krijgen, vooral als je abstractie gebruikt, zoals een ORM. Probeer Xdebug te gebruiken om je script te profileren en ontdek waar al dat geheugen is gebleven.
Antwoord 6, autoriteit 8%
Bij het toevoegen van 22,5 miljoen records aan een array met array_push kreeg ik steeds “geheugen uitgeput” fatale fouten bij ongeveer 20 miljoen records met 4G
als de geheugenlimiet in het bestand php.ini. Om dit op te lossen, heb ik de verklaring toegevoegd
$old = ini_set('memory_limit', '8192M');
bovenaan het bestand. Nu werkt alles goed. Ik weet niet of PHP een geheugenlek heeft. Dat is niet mijn taak, en het interesseert me ook niet. Ik moet gewoon mijn werk afmaken, en dit is gelukt.
Het programma is heel eenvoudig:
$fh = fopen($myfile);
while (!feof($fh)) {
array_push($file, stripslashes(fgets($fh)));
}
fclose($fh);
De fatale fout verwijst naar regel 3 totdat ik de geheugenlimiet verhoogde, wat
de fout geëlimineerd.
Antwoord 7, autoriteit 6%
Ik kreeg steeds deze foutmelding, zelfs met memory_limit
ingesteld in PHP.ini
, en de waarde correct uitgelezen met phpinfo()
.
Door dit te wijzigen:
memory_limit=4G
Hiervoor:
memory_limit=4096M
Dit heeft het probleem in PHP 7 verholpen.
Antwoord 8, autoriteit 3%
Als je de bovenstaande fout ziet – vooral als de (tried to allocate __ bytes)
een lage waarde is, kan dat een indicatie zijn van een oneindige lus, zoals een functie die zichzelf aanroept zonder uitweg:
function exhaustYourBytes()
{
return exhaustYourBytes();
}
Antwoord 9, autoriteit 3%
De hoofdmap van uw site:
ini_set('memory_limit', '1024M');
Antwoord 10, autoriteit 3%
Je kunt dit goed oplossen door memory_limit
te wijzigen op fastcgi/fpm:
$vim /etc/php5/fpm/php.ini
Verander het geheugen, zoals van 128 in 512, zie hieronder
; Maximum amount of memory a script may consume (128 MB)
; http://php.net/memory-limit
memory_limit = 128M
naar
; Maximum amount of memory a script may consume (128 MB)
; http://php.net/memory-limit
memory_limit = 512M
Antwoord 11, autoriteit 3%
Na het inschakelen van deze twee regels begon het te werken:
; Determines the size of the realpath cache to be used by PHP. This value should
; be increased on systems where PHP opens many files to reflect the quantity of
; the file operations performed.
; http://php.net/realpath-cache-size
realpath_cache_size = 16k
; Duration of time, in seconds for which to cache realpath information for a given
; file or directory. For systems with rarely changing files, consider increasing this
; value.
; http://php.net/realpath-cache-ttl
realpath_cache_ttl = 120
12, Autoriteit 2%
In Drupal 7 kunt u de geheugenlimiet in het bestand Instellingen.php wijzigen in uw sites / standaardmap. Ongeveer regel 260, zie je dit:
ini_set('memory_limit', '128M');
Zelfs als uw PHP.INI-instellingen hoog genoeg zijn, kunt u niet meer dan 128 & nbsp gebruiken; MB als dit niet is ingesteld in uw Drupal-instellingen.php-bestand.
13, Autoriteit 2%
Voor Drupal-gebruikers, het antwoord van deze Chris Lane op:
ini_set('memory_limit', '-1');
werkt, maar we moeten het net na de opening plaatsen
<?php
Tag in het bestand index.php in de hoofddirectory van uw site.
14, Autoriteit 2%
In plaats van de waarde memory_limit
in uw PHP.ini
-bestand te wijzigen, kunt u, als er een deel van uw code is dat veel geheugen zou kunnen gebruiken, de memory_limit
voordat die sectie wordt uitgevoerd, en vervang deze daarna.
$limit = ini_get('memory_limit');
ini_set('memory_limit', -1);
// ... do heavy stuff
ini_set('memory_limit', $limit);
Antwoord 15
Voeg gewoon een regel ini_set('memory_limit', '-1');
toe bovenaan uw webpagina.
En u kunt uw geheugen naar wens instellen op de plaats van -1, op 16M
, enz.
Antwoord 16
Met
PHP 5.3+ kunt u de geheugenlimiet wijzigen door een .user.ini
-bestand in de map public_html
te plaatsen.
Maak gewoon het bovenstaande bestand en typ de volgende regel erin:
memory_limit = 64M
Sommige cPanel-hosts accepteren alleen deze methode.
Antwoord 17
Crashpagina?
(Dit gebeurt wanneer MySQL grote rijen moet opvragen. Standaard is memory_limit
ingesteld op klein, wat veiliger was voor de hardware.)
U kunt de bestaande geheugenstatus van uw systeem controleren voordat u PHP.ini
verhoogt:
# free -m
total used free shared buffers cached
Mem: 64457 63791 666 0 1118 18273
-/+ buffers/cache: 44398 20058
Swap: 1021 0 1021
Hier heb ik het als volgt verhoogd en doe dan service httpd restart
om het probleem met de crashpagina op te lossen.
# grep memory_limit /etc/php.ini
memory_limit = 512M
Antwoord 18
Voor degenen die achter hun hoofd krabben om erachter te komen waarom deze kleine functie in hemelsnaam een geheugenlek zou moeten veroorzaken, soms door een klein foutje, een functie begint zichzelf recursief voor altijd aan te roepen.
Bijvoorbeeld een proxyklasse die dezelfde naam heeft voor een functie van het object dat deze gaat proxyen.
class Proxy {
private $actualObject;
public function doSomething() {
return $this->actualObjec->doSomething();
}
}
Soms vergeet je misschien dat kleine actualObjec-lid mee te nemen en omdat de proxy eigenlijk die doSomething
-methode heeft, zou PHP je geen foutmelding geven en voor een grote klasse zou het verborgen kunnen zijn voor de ogen een paar minuten om erachter te komen waarom het geheugen lekt.
Antwoord 19
Ik kreeg de onderstaande fout tijdens het uitvoeren van een dataset die kleiner was dan voorheen.
Fatale fout: toegestane geheugengrootte van 134217728 bytes uitgeput (geprobeerd om 4096 bytes toe te wijzen) in C:\workspace\image_management.php op regel 173
Omdat het zoeken naar de fout me hier bracht, dacht ik dat ik zou vermelden dat het niet altijd de technische oplossingen zijn in eerdere antwoorden, maar iets eenvoudigers. In mijn geval was dat Firefox. Voordat ik het programma uitvoerde, gebruikte het al 1.157 MB.
Het bleek dat ik gedurende een periode van dagen een video van 50 minuten had bekeken, en dat bracht de boel in de war. Het is het soort reparatie dat experts corrigeren zonder er zelfs maar over na te denken, maar voor mensen zoals ik is het de moeite waard om in gedachten te houden.
Antwoord 20
Het gebruik van yield
kan ook een oplossing zijn. Zie Generatorsyntaxis.
In plaats van het bestand PHP.ini
te wijzigen voor een grotere geheugenopslag, kan het probleem soms worden opgelost door een yield
in een lus te implementeren. Wat opbrengst doet, is in plaats van alle gegevens in één keer te dumpen, het leest ze één voor één, wat veel geheugengebruik bespaart.
Antwoord 21
Het script als volgt uitvoeren (bijvoorbeeld cron case): php5 /pathToScript/info.php
produceert dezelfde fout.
De juiste manier: php5 -cli /pathToScript/info.php
Antwoord 22
Als je een door WHM aangedreven VPS (virtual private server) gebruikt, kan het zijn dat je geen rechten hebt om PHP.INI rechtstreeks te bewerken; het systeem moet het doen. Ga in het configuratiescherm van de WHM-host naar Serviceconfiguratie→ PHP-configuratie-editoren wijzig memory_limit
:
Antwoord 23
Ik vind het handig bij het opnemen of vereisen van _dbconnection.php_
en _functions.php
in bestanden die daadwerkelijk worden verwerkt, in plaats van in de koptekst. Wat op zich is inbegrepen.
Dus als uw headeren footerzijn opgenomen, voegt u gewoon al uw functionele bestanden toe voordat de header wordt opgenomen.
Antwoord 24
In mijn geval op mac (Catalina – Xampp) was er geen geladen bestand, dus ik moest dit eerst doen.
sudo cp /etc/php.ini.default /etc/php.ini
sudo nano /etc/php.ini
Verander dan memory_limit = 512M
Start vervolgens Apache opnieuw en controleer of het bestand is geladen
php -i | grep php.ini
Resultaat was
Configuration File (php.ini) Path => /etc
Loaded Configuration File => /etc/php.ini
Eindelijk controleren
php -r "echo ini_get('memory_limit').PHP_EOL;"
Antwoord 25
De meest voorkomende oorzaak van deze foutmelding voor mij is het weglaten van de “++” operator uit een PHP “for” statement. Dit zorgt ervoor dat de lus voor altijd doorgaat, ongeacht hoeveel geheugen je toestaat te gebruiken. Het is een eenvoudige syntaxisfout, maar is moeilijk te detecteren door de compiler of het runtime-systeem. Het is gemakkelijk voor ons om te corrigeren als we denken ernaar te zoeken!
Maar stel dat u een algemene procedure wilt om zo’n lus vroegtijdig te stoppen en de fout te melden? Je kunt eenvoudig elk van je loops (of in ieder geval de binnenste loops) instrumenteren zoals hieronder wordt besproken.
In sommige gevallen, zoals recursie binnen uitzonderingen, mislukt set_time_limit
en blijft de browser proberen de PHP-uitvoer te laden, ofwel met een oneindige lus of met de fatale foutmelding die het onderwerp is van dit vraag.
Door de toegestane toewijzingsgrootte aan het begin van uw code te verkleinen, kunt u mogelijk de fatale fout voorkomen, zoals besproken in de andere antwoorden.
Dan houdt u misschien een programma over dat eindigt, maar nog steeds moeilijk te debuggen is.
Of uw programma nu wel of niet eindigt, instrumenteer uw code door BreakLoop()
-aanroepen in uw programma in te voegen om controle te krijgen en erachter te komen welke lus of recursie in uw programma het probleem veroorzaakt.
>
De definitie van BreakLoop is als volgt:
function BreakLoop($MaxRepetitions=500,$LoopSite="unspecified")
{
static $Sites=[];
if (!@$Sites[$LoopSite] || !$MaxRepetitions)
$Sites[$LoopSite]=['n'=>0, 'if'=>0];
if (!$MaxRepetitions)
return;
if (++$Sites[$LoopSite]['n'] >= $MaxRepetitions)
{
$S=debug_backtrace(); // array_reverse
$info=$S[0];
$File=$info['file'];
$Line=$info['line'];
exit("*** Loop for site $LoopSite was interrupted after $MaxRepetitions repetitions. In file $File at line $Line.");
}
} // BreakLoop
Het argument $LoopSite kan de naam zijn van een functie in uw code. Het is niet echt nodig, omdat de foutmelding die je krijgt je zal verwijzen naar de regel met de BreakLoop()-aanroep.
Antwoord 26
wijzig ;memory_limit=512M
naar ;memory_limit=-1
in
het is te gevaarlijk voor een server
Je PHP-code kan ergens een geheugenlek hebben en je vertelt de server om gewoon al het geheugen te gebruiken dat hij wil. Je zou het probleem helemaal niet hebben opgelost. Als u uw server in de gaten houdt, zult u zien dat deze nu waarschijnlijk het grootste deel van het RAM-geheugen gebruikt en zelfs naar schijf overschakelt.
Antwoord 27
In mijn geval was het een kort probleem met de manier waarop een functie is geschreven. Een geheugenlek kan worden veroorzaakt door een nieuwe waarde toe te wijzen aan de ingangsvariabele van een functie, b.v.:
/**
* Memory leak function that illustrates unintentional bad code
* @param $variable - input function that will be assigned a new value
* @return null
**/
function doSomehting($variable){
$variable = 'set value';
// Or
$variable .= 'set value';
}
28
Ik heb twee dya’s doorgebracht met een oplossing voor dit en ik dacht dat dit veroorzaakt was in een oproep met PDO toen ik
belde
$stmt->bindParam(":PERIOD", $period);
en de periode van de variabelen was een
empty string ''
Dus dit probleem kan meerdere root-oorzaak hebben, mijn advies aan u is dat een vallen en opstaan of een bisectiemethode voor een root-oorzaak vinden, verwijderen, code verwijderen en proberen te zoeken wat de lijncode is die faalt
Update: Ik heb ook geconfronteerd met deze fout met de methode $ PDO- & GT; Query () Ik gebruikte $ PDO- & GT; voorbereiden () en werkte goed, dus, terwijl ik
had
$sql = "SELECT * FROM COURSE_DETAILS where ACTIVE = 1 AND COURSE_DETAILS_ID = $id";
$stmt = getConnection()->query($sql);
$courseDetails = $stmt->fetchAll(PDO::FETCH_ASSOC)
Dan veranderde ik dit naar
$sql = "SELECT * FROM COURSE_DETAILS where ACTIVE = 1 AND COURSE_DETAILS_ID = ?";
$stmt = getConnection()->prepare($sql);
$stmt->execute(array($id));
en op magische wijze de geheugenfout verdwenen!
29
Deze vraag is een paar jaar geleden gesteld, dus hoewel mijn feiten niet hetzelfde zijn, kreeg ik deze fout onlangs ook bij het ontleden van een html-tabel op de server in een lus. De reden voor de fout was dat de html werd geparseerd met dubbele aanhalingstekens die waren samengevoegd tot een variabele $table
, terwijl tegelijkertijd tekenreeksen op meerdere regels werden samengevoegd.
$table = "<table>\n";
$table .= "<tbody>\n";
foreach ($data as $item) {
$table .= "<tr>\n";
// this caused the Fatal Error: Allowed Memory Size of 134217728 Bytes Exhausted
$table .= "<td>$item->description</td><td>$item->qty</td>" .
$table .= "<td>$item->price_incl</td><td>$item->price->vat</td>" .
$table .= "<td>$item->price_excl</td><td>$item->available</td>" .
$table .= "</tr>\n";
}
$table .= "</tbody>";
$table .= "</table>\n";
De bovenstaande fout was vreemd voor mij, maar aangezien ik de string al aan het samenvoegen was met de $table
variabele, lijkt het nu dwaas dat ik dit had geprobeerd. De oplossing was om ofwel de aaneenschakeling van de variabele op regel 7 en 8 te verwijderen, ofwel het symbool voor de aaneenschakeling van de eindregel op regel 6, 7 en 8 te verwijderen.