2010-07-06 11 views
59

Więc jak duże może być $variable w PHP? Próbowałem to przetestować, ale nie jestem pewien, czy mam wystarczająco dużo pamięci systemowej (~ 2 gb). Sądzę, że musi istnieć jakiś limit. Co się dzieje, gdy ciąg staje się zbyt duży? Czy jest on połączony, czy PHP wyrzuca wyjątek?Jaka jest maksymalna długość łańcucha w PHP?

+5

co próbujesz w ogóle zrobić? – Sarfraz

+0

@sAc Chcę wiedzieć więcej o PHP. Wiem, nie mogę używać php do ciężkich operacji pamięciowych z powodu poważnych wycieków pamięci. – rook

+1

W php7 usuwają to ograniczenie: http://stackoverflow.com/a/31085071/1090562 –

Odpowiedz

88

http://php.net/manual/en/language.types.string.php mówi:

Uwaga: Począwszy od PHP 7.0.0, nie ma szczególnych ograniczeń odnośnie długości łańcucha na 64-bitowych buduje. On buduje 32-bitowy i we wcześniejszych wersjach, ciąg może być tak duży, jak do 2 GB (2147483647 bajtów maksimum)

w PHP 5.x, struny były ograniczone do 2 -1 bajtów, ponieważ kod wewnętrzny zapisał długość w podpisanej 32-bitowej liczbie całkowitej.


można slurp w zawartości całego pliku, na przykład przy użyciu file_get_contents()

Jednak skrypt PHP ma limit na ilość pamięci może przeznaczyć dla wszystkich zmiennych w danym wykonywania skryptu, więc to skutecznie ustawia ograniczenie długości pojedynczej zmiennej łańcuchowej.

Ten limit to dyrektywa memory_limit w pliku konfiguracyjnym php.ini. Limit pamięci wynosi domyślnie 128 MB w PHP 5.2 i 8 MB w starszych wersjach.

Jeśli nie określisz limitu pamięci w pliku php.ini, użyje on wartości domyślnej, która jest wkompilowana w plik binarny PHP. Teoretycznie możesz zmodyfikować źródło i przebudować PHP, aby zmienić tę domyślną wartość.

Jeśli określisz -1 jako limit pamięci w pliku php.ini, przestanie ono sprawdzać i pozwoli twojemu skryptowi zużyć tyle pamięci, ile przydzieli system operacyjny. Jest to nadal praktyczne ograniczenie, ale zależy od zasobów systemowych i architektury.


Re komentarz z @ c2:

Oto test:

<?php 

-- limit memory usage to 1MB 
ini_set('memory_limit', 1024*1024); 

-- initially, PHP seems to allocate 768KB for basic operation 
printf("memory: %d\n", memory_get_usage(true)); 

$str = str_repeat('a', 255*1024); 
echo "Allocated string of 255KB\n"; 

-- now we have allocated all of the 1MB of memory allowed 
printf("memory: %d\n", memory_get_usage(true)); 

-- going over the limit causes a fatal error, so no output follows 
$str = str_repeat('a', 256*1024); 
echo "Allocated string of 256KB\n"; 
printf("memory: %d\n", memory_get_usage(true)); 
+0

Jaki jest najlepszy sposób pracy w ramach limitu pamięci, jeśli naprawdę potrzebujemy długich łańcuchów? – Pacerier

+0

Gdy PHP.net stwierdza "ciąg notatek może mieć wielkość 2 GB". http://php.net/manual/en/language.types.string.php czy to oznacza, że ​​może przekroczyć * 2 GB? – Pacerier

+0

@Pacerier, dobry połów! Ta notatka nie znajdowała się na stronie podręcznika, kiedy pierwszy raz odpowiedziałem na to pytanie w 2010 r. Zmienię powyższą odpowiedź. –

16

String może być tak duży, jak 2GB.
Source

+7

Deweloper może zostać zwolniony – James

4

długość ciąg PHP jest ograniczone przez sposób ciągi są reprezentowane w PHP; pamięć nie ma z tym nic wspólnego.

Zgodnie z phpinternalsbook.com ciągi są przechowywane w struct {char * val; int len; } i ponieważ maksymalny rozmiar int w C wynosi 4 bajty, efektywnie ogranicza maksymalny rozmiar ciągu do 2 GB.

+1

.. dlaczego f nie użyłoby niepodpisanego int tutaj? nie jak struna może być NIŻSZY NIŻ 0 BYTES LONG: p – hanshenrik

+1

Nie jest całkowicie poprawne. 2 GB to 31-bit. Trochę marnują się, używając podpisanego typu danych.Być może miało to na celu uproszczenie rzeczy, takich jak kontrole przepełnienia bez konieczności stosowania większej wartości lub specyfikacji (concat A + B, całkowita suma = A. L. + B.len, jeśli całkowita> TYPE_MAX/2 to błąd), myślę, że C umożliwia kontrolę przepełnienia bez wpadania do zespołu. – jgmjgm

+0

@jgmjgm 2 GB w 31-bitach, ponieważ 32-ty bit jest dla znaku. Jeśli byłby "unsinged int len", to masz 32bits i 4GB – Jack

2

Maksymalna długość zmiennej łańcuchowej wynosi tylko 2GiB - (2^(32-1) bitów). Zmienne można adresować na podstawie znaku (8 bitów/1 bajt), a adresowanie odbywa się za pomocą liczb całkowitych ze znakiem, dlatego limit jest taki, jaki jest. Tablice mogą zawierać wiele zmiennych, z których każda spełnia poprzednie ograniczenie, ale może mieć łączny rozmiar aż do limitu_umysłów, którego podlega również zmienna łańcuchowa.

2

W nowej nadchodzącej php7 wśród wielu innych cech, dodali wsparcie dla strings bigger than 2^31 bytes:

Wsparcie dla ciągów o długości> = 2^31 bajtów w 64 bit buduje.

Niestety nie sprecyzowały, o ile większa może być.

+0

Być może 2^63 - 1? Nie wiem nawet, czy taka ilość pamięci RAM jest dostępna gdzieś .... – hakre

+0

Teoretycznie może pozwolić na 2^32 lub 2^64. Z jakiegokolwiek powodu używane są podpisane int lub longs. Ponieważ złamałoby to kod w wielu miejscach (jeśli len jgmjgm

+0

Zakładam jego 0x7FFFFFFFFFFFFFFF lub 9223372036854775807 bajtów (lub 9.2 eksabajtów), minus to, co PHP już używa, minus to, co ASLR marnuje, ponieważ, wiesz, 64-bitowa przestrzeń pamięci wirtualnej byłaby wyczerpana: D – hanshenrik

0

Aby poprawnie odpowiedzieć na ten temat, należy wziąć pod uwagę wewnętrzne lub wewnętrzne PHP, dla którego zbudowany jest PHP.

Aby odpowiedzieć na to z punktu widzenia typowego systemu Linux na platformie x86 ...

rozmiarów typów w C: https://usrmisc.wordpress.com/2012/12/27/integer-sizes-in-c-on-32-bit-and-64-bit-linux/

Rodzaje stosowanych w PHP zmienne: http://php.net/manual/en/internals2.variables.intro.php

ciągi są zawsze 2GB ponieważ długość jest zawsze 32-bitowa i trochę się marnuje, ponieważ używa int, a nie uint. int jest niepraktyczny dla długości powyżej 2 GB, ponieważ wymaga rzutu, aby uniknąć łamania arytmetycznych lub "niż" porównań. Dodatkowy bit jest prawdopodobnie używany do kontroli przepełnienia.

Dziwnie, klawisze skrótów mogą wewnętrznie obsługiwać 4 GB, ponieważ używany jest uint, chociaż nigdy nie poddałem tego testowi. Klucze mieszające PHP mają +1 do długości dla kończącego bajtu zerowego, który według mojej wiedzy zostanie zignorowany, więc może wymagać niepodpisania dla tego przypadku krawędzi, zamiast pozwolić na dłuższe klawisze.

System 32-bitowy może nakładać więcej limitów zewnętrznych.

Powiązane problemy