Reklāma:

PHP un 64 biti

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.

Šie ir tie 6 komentāri

    • #1. 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 !

    • Saite uz šo komentāru
    • #3. 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

    • Saite uz šo komentāru
    • #5. 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, ..).

    • Saite uz šo komentāru
    • #6. 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.

    • Saite uz šo komentāru

Moderācija: Daži vārdi var gadīties, ka ir iz melnās listes (viagra and stuff). Tādi komentāri tiek aizturēti, pirms parādās lapā. Ja Tavs komentārs neparādās uzreizi, būs vien jāpagaida, līdz es jamo izlasīšu. Protams, ka paturu tiesības sev netīkošos komentārus dzēst, iemeslu neminot.