Fatale fout: toegestaan ​​geheugengrootte van 134217728 bytes uitgeput (CodeNigniter + XML-RPC)

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_limitdoor 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_limitnaar 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 = 512Mof 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_limitaanpassen 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 128Mtoe (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 4Gals 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_limitingesteld 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_limitte 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_limitin uw PHP.ini-bestand te wijzigen, kunt u, als er een deel van uw code is dat veel geheugen zou kunnen gebruiken, de memory_limitvoordat 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_htmlte 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_limitingesteld op klein, wat veiliger was voor de hardware.)

U kunt de bestaande geheugenstatus van uw systeem controleren voordat u PHP.iniverhoogt:

# 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 restartom 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 yieldkan ook een oplossing zijn. Zie Generatorsyntaxis.

In plaats van het bestand PHP.inite wijzigen voor een grotere geheugenopslag, kan het probleem soms worden opgelost door een yieldin 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.phpproduceert 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 ServiceconfiguratiePHP-configuratie-editoren wijzig memory_limit:


Antwoord 23

Ik vind het handig bij het opnemen of vereisen van _dbconnection.php_en _functions.phpin 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_limiten 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 $tablevariabele, 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.

Other episodes