Results 1 to 9 of 9

Thread: Delphi2009 + Int64 onterechte range check?

  1. #1

    Delphi2009 + Int64 onterechte range check?

    Hey allemaal,

    Ik gebruik in Delphi2009 een Int64 voor een "disk space" overzicht.
    Hier ik kreeg opeens problemen:



    var DS:Int64;

    DS := 2048 * 1024 * 1024; // = 2147483648


    Dit is ruim binnen de Int64 range van 9223372036854775808, maar toch weigert Delphi te compilen, met de mededeling:

    [DCC Error] Unit1.pas(3195): E2099 Overflow in conversion or arithmetic operation

    Als ik overflow checking/range checking uitschakel compiled Delphi wel, maar dan word de waarde niet goed verwerkt.

    Iemand enig idee? Het lijkt alsof Delphi deze Int64 als een gewone integer behandelt

  2. #2
    Nee, Delphi ziet de expressie als gewone integers. Het integer resultaat wordt naderhand pas omgezet naar int64. Volgens mij kun je de berekening al int64 maken door één van de operands (de getallen) te typecasten naar Int64.
    1+1=b

  3. #3
    Hey da's snel, thanks!

    DS := 922337203685477; // geen probleem
    DS := 3000 * 1024 * 1024; // probleem voor compilen
    DS := Int64(3000 * 1024 * 1024); // probleem voor compilen
    DS := Int64(ServerSpace.AsInteger * 1024 * 1024); // probleem on runtime

    [ServerSpace is een TJvSpinEdit, boven de 2048 werkt het niet meer]

    Of typecast ik nu helemaal verkeerd?

    ========== edit ====

    Je schreef het goed, EEN van de operands, niet gezamelijk.

    Dit werkt perfect:

    DS := Int64(ServerSpace.AsInteger) * Int64(1048576);

    Nogmaals thanks!!
    Last edited by Sadhu; 22-Apr-09 at 14:53. Reason: oplossing gevonden na beter lezen ;-)

  4. #4
    mov rax,marcov; push rax marcov's Avatar
    Join Date
    Apr 2004
    Location
    Ehv, Nl
    Posts
    10,357

    Smile

    Quote Originally Posted by GolezTrol View Post
    Nee, Delphi ziet de expressie als gewone integers. Het integer resultaat wordt naderhand pas omgezet naar int64. Volgens mij kun je de berekening al int64 maken door één van de operands (de getallen) te typecasten naar Int64.
    IMHO is dat een bug. Een literal heeft nl geen type, en de rechter kant is geheel compiletime evalueerbaar.

    FPC had deze bug ook in v1, maar sinds v2 is het hele binnenwerk van de compiler naar 64-bit uitgebreid.

    Er is zelfs sprake geweest literals default op 128-bit te zetten, maar ik weet niet of dit uitgevoerd is. In theorie zou je met 64-bits systemen zelfs naar 256 bit moeten.

    De reden hiervoor is dat arithmetische functies (+ -/*) redelijk doendelijk zijn voor een type dat twee keer zo groot is als een CPU register.

    Echter een signed+unsigned waarde van (n*2)-bits, hebben een range van 1.5 * (n*2)-bits, waardoor het niet in een (n*2)-bits integer kan. Vandaar dat je voor literals NOG een type groter moet gaan zitten (n*2+1, maar in praktijk n*2*2). Gelukkig is het rekenen met literals in een compiler maar relatief verwaarloosbaar onderdeel.

    Oftewel :

    Op n=32-bit kan je int64/qword ondersteunen. Range is - (2^63) .. (2^64-1), hetgeen niet in een 64-bits waarde past. Dus je hebt een 128-bits type nodig.

    Op n=64-bit kan je int128/oword ondersteunen. Range is - (2^127) .. (2^128-1), hetgeen niet in een 128-bits waarde past. Dus je hebt een 256-bits type nodig.
    Last edited by marcov; 22-Apr-09 at 17:30.

  5. #5
    Quote Originally Posted by marcov View Post
    IMHO is dat een bug
    Er gingen idd meer van dat soort geluiden over deze kwestie over het Inet.

  6. #6
    Tja.. Als er staat beschreven dat een untyped constante in 32 bit gepropt wordt (wat niet gek is voor een 32 bit taal op een 32 bit OS) dan is het geen bug maar een feature.

    Het feit dat Lazarus het anders ('beter') doet is misschien een voordeel voor Lazarus, maar aan de andere kant lijkt het me ook niet zo logisch dat de compiler maar even 128 bits gaat reserveren als ik de waarde 1024 in een constante zet. Dat lijkt me niet zo efficient om mee te rekenen.

    Jij als purist en verdediger van micromalistische optimalisaties, Marcov, zou het er toch niet mee eens moeten zijn dat de compiler kiest voor "arithmetische functies " die "redelijk doendelijk zijn" en niet voor de snelste manier, tenzij op expliciet verzoek (dmv bijvoorbeeld een typecast).
    1+1=b

  7. #7
    mov rax,marcov; push rax marcov's Avatar
    Join Date
    Apr 2004
    Location
    Ehv, Nl
    Posts
    10,357
    Quote Originally Posted by GolezTrol View Post
    32 bit taal
    Wel dat is dus niet zo, want dan zou

    delphi Code:
    1. <ietsvanint64>:=100000000000;

    ook niet werken en gewrapped worden naar 32-bit. Want de compiler heeft daar ook een untyped rechter lid, maar neemt niet automatisch aan dat het daar 64-bit is.

    We weten allemaal dat de Cardinal/dword/int64 implementatie in fases is gegaan, en in theorie zou dit ongefixed kunnen zijn om ergens geen compatibiliteit te breken.

    Zelf denk ik echter eerder dat het simpelweg te veel werk was voor wat het opleverde (het fixed alleen het literal *literal*literal geval). Hetzelfde voor het feit dat Delphi nog altijd geen 64-bit unsigned heeft.

    FPC is echter vrijwel totaal herschreven van v1 naar v2, en dus toen is het gewoon simpelweg direct goed gedaan, Qword incluis.

    Verder vallen sommige van deze problemen eerder op omdat FPC in zichzelf geschreven is. Oftewel, de taal moet in FPC's geval de arithmetic kunnen doen die de implementatie nodig heeft. In Delphi, wat in C++ is geschreven hoeft dit niet.

    Het feit dat Lazarus het anders ('beter') doet is misschien een voordeel voor Lazarus, maar aan de andere kant lijkt het me ook niet zo logisch dat de compiler maar even 128 bits gaat reserveren als ik de waarde 1024 in een constante zet.
    Dat lijkt me niet zo efficient om mee te rekenen.
    Dat is het ook niet. Maar in dit geval doet het er niet toe.

    Jij als purist en verdediger van micromalistische optimalisaties, Marcov
    Ik neem aan dat je daarmee impliciet "is kritisch" bedoelt, en zal het dan maar als compliment zien.

    , zou het er toch niet mee eens moeten zijn dat de compiler kiest voor "arithmetische functies " die "redelijk doendelijk zijn" en niet voor de snelste manier, tenzij op expliciet verzoek (dmv bijvoorbeeld een typecast).
    Jij snapt het dus niet?!? Het is in de compiler zelf, ALLEEN de arithmetic waar de compiler die compiletime constantes als die (1024*1024*2048) in het voorbeeld uitrekent. Van die 128-bitness komt dus niets in de uiteindelijke gegenereerde binary, en doorgaans zorgen early outs ervoor dat het effectief een 32 of 64-bit arithmetic is. De gegenereerde code wordt aangepast aan de breedte van de uiteindelijke constante.

    En de tijd om een int64 vermenigvuldiging (of zelfs 128 bit) te doen in de compiler is nu eenmaal te verwaarlozen ten opzichte van al die string parsing (en al helemaal nu die met D2009 unicode wordt).

    Let op dat dat 128-bittige het extreme geval is (zie eerder uitleg). Als je het goedvindt dat literals van 2^63-1 tot 2^64-1, het verschil in range tussen signed en unsigned 64-bit, alleen met een expliciete typecast werken, dan is int 64 + ingebouwde arithmetic genoeg.

    (b.v.qword($FFFFFFFFFFFFFFFF) div sizeof(type) ipv $FFFFFFFFFFFFF div sizeof(type). De typecast is om te voorkomen dat de qword constante in een standaard arithemetiek (64-bit) wordt uitgerekend, waar het resultaat 0 zou zijn (-1 div sizeof(type)) Sommige mensen kennen dit soort problemen misschien nog met de oude dword en cardinal constanten van voor de int64 introductie (D3?). Het is in feite hetzelfde probleem )

    Maar goed, ik zal het voorstellen als additie voor de "known problems" site zetten, want het is en blijft een afwijking.
    Last edited by marcov; 22-Apr-09 at 19:16.

  8. #8
    Quote Originally Posted by marcov View Post
    Ik neem aan dat je daarmee impliciet "is kritisch" bedoelt, en zal het dan maar als compliment zien.
    Of ik het altijd nodig vind is een tweede, maar dit was inderdaad zeker niet beledigend bedoeld.

    Quote Originally Posted by marcov View Post
    Het is in de compiler zelf...
    Logisch inderdaad, maar daar had ik even niet aan gedacht.

    Ok, ok. Dan is het een bug.
    1+1=b

  9. #9

    Talking

    Da's een goed teken, een stortvloed aan extra info op me vraag,
    nooit te lui om te leren

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •