✉️ Saņem šito visu e-pastā. Tā vietā, lai palaistu garām kaut ko no tā, ko es rakstu savā blogā, tagad vari pierakstīties un saņemt e-pastā visu, ko es te rakstu. Tas nav bieži.

← Uz sākumu

PHP un 64 biti

2009. gada 4. martā, 6 komentāri

Es, šķiet, pirmo reizi mūžā šodien saskāros ar problēmu, kuras sakne ir tanī, ka 32bit sistēmas un 64bit sistēmas ir ne pārāk viegli savietojamas.

Eksistē maģiska funkcija, kā unpack(). Konkrētajā gadījumā man no četriem secīgiem baitiem nepieciešams "izpakot" 32 bitu naturālu skaitli big endian baitu secībā. Nekādu problēmu. Neskatoties ne uz ko, tas vienmēr ir izdevies bez problēmām. Šodien, uz kādas 64 bitu sistēmas radās nepieciešamība palaist attiecīgo skriptu nevis zem PHP4, kā līdz šim, bet nu jau zem PHP5 (uz 32bit PHP5 problēmu nav). Un tad nu sākās.

list(,$command_id) = unpack('N', \ chr(0x80) . chr(0x00) . chr(0x00) . chr(0x09)); # Iegūstam -2147483639

Tas nekas, ka reāli tas ir negatīvs skaitlis, neskatoties uz unpack norādīto informāciju. Sekojošais kods visu noliek savās vietās un iegūstam pozitīvu skaitli:

$command_id = hexdec(dechex($command_id)); # Iegūstam 2147483657

Taču, uz 64bit PHP5 man šāda operācija pēkšņi sāka izsniegt skaitli 1.8446744071562E+19. Neiedziļinoties detaļās - kāpēc tā, sapratu, ka esmu nepareizi darījis. Tā vietā, lai atrisinātu problēmu ar pirmo atrasto metodi, man vajadzēja to saprast līdz saknei un risināt ar pirmo pareizo. Un tā būtu:

$command_id &= 0xffffffff;

Šis atrisina problēmu uz 64bit sistēmām, un neko nesalauž uz 32bit. Kā jau minēju, uz tās pašas kastes PHP4 uzvedās korekti.

Tu atbildi augstāk redzamajam komentāram. Atcelt

Gravatar Taai

2009. gada 4. martā, plkst. 19:47

Bet uzmanies un ņem vērā, ka dechex un hexdec funkcijām ir skaitļa limits - 4294967295 !

Gravatar binary

2009. gada 4. martā, plkst. 21:56

Taai, droši zini, ka 4294967295? PHP nesupporto unsigned integerus.

Gravatar binary

2009. gada 4. martā, plkst. 21:58

brr... tikko pamēģināju uz 32bit windas paskatīties, ko PHP teiks par echo 4294967295-1, echo 4294967295+1, ... works like a charm

Gravatar binary

2009. gada 4. martā, plkst. 22:02

nevermind. pieleca viss.

Gravatar bubu

2009. gada 4. martā, plkst. 22:35

Problēma ir src/ext/standard/pack.c failā. Tur jāizmet ārā 790 rinda. Un arī 793. rinda, jo "V" arī ir unsigned. Un jāpielabo 788. rindu, lai "L" arī neuzstāda issigned mainīgo, jo "L" arī ir unsigned. unsigned short'iem gan tur par brīnumu source viss ir korekti.

Tur vispār viss ir dīvaini. Izrādās "i" un "I" nebūs 8 baiti uz x86-64, jo tur tiek lietots sizeof(int) izmērs - un tas arī x86-64 ir 4 baiti. Diezgan dīvaini. Jo kautkas cits tas ir tikai DOS'ā (2 baiti) vai kautkādās embedded sistēmās, kur diez vai php ir vajadzīgs. Tāda tipa kā sizeof(long) vai sizeof(void*), kuri tiešām atšķirtos starp x86 un x86-64, tur nemaz nav.

Dīvains tas php ir... Tādā ziņā pitonā ir daudz konsistentāk šitā pakošana un atpakošana saistībā ar C tipiem (int, long, ..).

Gravatar noisex

2009. gada 5. martā, plkst. 23:31

uz tas sistemas, kur izmantoju unpack/ord/hexdec utt kombinacijas stav uz 32bit os..nevaru notestet. bet nu prikola pec varetu pamegjinat.