2010-10-29 2 views
59

Eventuali duplicati:
How to also prepare for 64-bits when migrating to Delphi 2010 and UnicodeCome devo preparare i miei programmi Delphi a 32 bit per un eventuale compilatore a 64 bit?

Poiché credo che 64bit Delphi compilatore apparirà presto, io sono curioso di sapere se qualcuno sa che tipo di programmi che sono ora 32bit compila e funziona senza modifiche quando si utilizza 64 bit comp iler.

e se c'è una regola generale, che tipo di cambiamenti dovremmo sistematicamente fare nei nostri vecchi programmi da compilare come 64bit?

E 'bene essere preparati quando il 64bit compilatore improvvisamente essere qui ...

Ogni suggerimento sarà molto apprezzato.

+8

Nominato per riapertura poiché questa domanda sembra produrre risposte infinitamente più utili rispetto al duplicato contrassegnato. – Justin

+3

Cosa ti fa pensare che Embarcadero pubblicherà presto un compilatore Delphi a 64 bit? – Rowan

+0

Credo quello che promettono: http://edn.embarcadero.com/article/39934 Qualcuno ha informazioni che Delphi 64 non sarà disponibile nel 2011? – Petra

risposta

0

Come ipotesi completa, qualsiasi codice che non dipende da una specifica dimensione di parola, o può adattare la sua dimensione di parola in base a ciò che il compilatore dice, andrà bene.

+0

Cosa stai chiamando una "parola"? In Delphi, una parola è sempre un valore a 16 bit. Quindi immagino che tu abbia parlato di "NativeInt" ... perché DWord rimarrà sempre a 32 bit, come il numero intero resterà anche a 32 bit ... –

+0

Sto usando la definizione CE, non la definizione Delphi. –

3

La stragrande maggioranza delle applicazioni semplici dovrebbe funzionare correttamente. Per quanto posso vedere, solo le applicazioni che utilizzano manualmente i puntatori sono a rischio. Infatti, se un puntatore ora è a 64 bit e lo si utilizza nei calcoli insieme a numeri interi o cardinali (che sono ancora a 32 bit per impostazione predefinita), si avranno dei problemi. Penso anche che sia piuttosto comune che le dichiarazioni per le funzioni API che assumono i puntatori come argomenti utilizzano cardinal s invece del tipo intero nativo (senza segno).

per rendere il codice che funziona bene su qualsiasi piattaforma, si dovrebbe usare NativeUInt s (IIRC, non hanno un compilatore Deplhi adesso) invece di cardinal s quando si lavora con puntatori e interi contemporaneamente.

+1

Penso che sia piuttosto comune dichiarare API che prende i puntatori come parametri dei puntatori :) Anche NativeUInt è un tipo relativamente nuovo, una volta che era Cardinale a svolgere il suo ruolo. Ci sono alcuni problemi, pensate alla proprietà Tag (nessuno sa ancora cosa diventerà), i tipi wParam/lParam nei messaggi Windows, le dimensioni dei record potrebbero cambiare. –

+2

@Idsandon: Vero, ma per molte persone un puntatore è solo un nome di fantasia di un cardinale e quel "malinteso" ha funzionato bene per un tempo piuttosto lungo. Quindi è un possibile problema. Quindi il 'Tag' potrebbe diventare 64-bit? Suppongo che non infrangerà alcun codice esistente, anche se ... –

+1

http://twitter.com/#!/kylix_rd "Come speculato, la proprietà Tag diventerà NativeInt." –

4

A seconda del codice, è possibile provare a compilarlo utilizzando FreePascal, che supporta la compilazione a 32 e 64 bit. Il compilatore ti avviserà di eventuali errori nel codice.

3

Fintanto che Embarcadero non rilascia informazioni ufficiali sulla loro implementazione a 64 bit non è facile dirlo. Dovresti controllare qualsiasi cast da/verso Pointer, Integer e Cardinal assumendo che siano le dimensioni della piattaforma nativa, comprese le proprietà e i riferimenti degli oggetti (ad esempio, l'archiviazione di un intero in una proprietà TObject, che è un puntatore o l'utilizzo di Tag per memorizzare riferimenti e non numeri).

È inoltre necessario assicurarsi che nessun codice si basi sull'effetto "wrap-around" quando si incrementa (o decrementa) un valore alla sua dimensione massima (minima).

Controllare qualsiasi codice nelle strutture che si basa sulla dimensione dei dati e non utilizzare SizeOf() correttamente, e in generale che SizeOf() viene sempre utilizzato quando il datasize è importante. Controlla il codice che scrive/legge i dati sui file, se le dimensioni possono cambiare, specialmente se i dati devono essere scambiati tra il codice 32 e 64 bit.

Controllare le modifiche di Win64, se l'applicazione chiama l'API e gestisce direttamente i messaggi di Windows. Il codice ASM con codice a mano deve essere controllato per la compatibilità a 64 bit (ci sono regole molto più rigide per scrivere un assemblatore a 64 bit).

+1

TComponent.Tag deve essere NativeInt per gestire il caso previsto di persone che eseguono il casting di riferimenti TObject e simili dentro e fuori di esso. Integer e Cardinal dovrebbero rimanere gli stessi a 32 bit, poiché questa è la politica generale su Windows a 64 bit; dovrebbe anche ridurre i cambiamenti semantici di commutazione del testimone del bersaglio. L'assemblatore incorporato a 64 bit probabilmente non esiste; si spera che il supporto di collegamento esista per nas o simili. –

+0

+1 principalmente per la menzione della compatibilità ASM, in quanto ho avuto quei problemi esatti dal rilascio di Delphi XE2 (x64). –

8

Prima di tutto, FreePascal offre già il supporto a 64 bit. Non è Delphi, però.
In secondo luogo, mi aspetto circa gli stessi problemi che esistevano nel tempo in cui Delphi 1 è stato aggiornato a Delphi 2. Il problema più grande è principalmente legato allo spazio degli indirizzi e il problema qui è che i puntatori verranno allargati da 4 byte a 8 byte . In WIN16 utilizzavano 2 byte e un trucco era necessario per superare il limite di 64 KB utilizzando segmenti e offset per i puntatori. (Con la possibilità di utilizzare segmenti predefiniti per più attività.)
È anche probabile che alcuni tipi di dati diventeranno più grandi di quanto non lo siano ora. Il tipo intero sarà di 8 byte, molto probabilmente. (Utilizzato per essere solo 2 byte in Windows 2.) Anche le enumerazioni diventeranno più grandi. Ma la maggior parte degli altri tipi di dati probabilmente manterranno le loro dimensioni attuali, quindi non troppe modifiche qui.
Un altro problema saranno i requisiti di memoria. Poiché i puntatori avranno una lunghezza di 8 byte, un'applicazione che utilizza molti di essi mangerà molta più memoria. Una lista con 10.000 puntatori aumenterà da 40.000 byte a 80.000 byte. Potresti voler utilizzare un po 'di memoria in più rispetto a un sistema a 32 bit.
Anche la velocità cambierà leggermente. Poiché il processore ora gestisce 8 byte allo stesso tempo, può elaborare i dati molto più velocemente. Ma dal momento che i puntatori e alcuni tipi di dati diventano più grandi, la ricezione o l'invio di questi a qualche dispositivo o memoria sarà un po 'più lento. In generale, le tue applicazioni saranno leggermente più veloci in generale, ma alcune parti potrebbero effettivamente diventare più lente!
Infine, le modifiche all'API di Windows richiedono l'utilizzo delle funzioni API a 64 bit. Forse il compilatore Delphi farà qualcosa di intelligente per consentire al codice di chiamare le funzioni API a 32 bit, ma questo rallenterebbe le prestazioni perché il processore ora passa dalla modalità nativa a 64 bit alla modalità emulata a 32 bit.

+7

Su Windows a 64 bit, il modello è per int e long per rimanere a 32 bit. Corrispondentemente, Delphi seguirà con Integer e Longint rimanendo a 32 bit. Inoltre, in Delphi, le enumerazioni hanno sempre avuto il tipo più piccolo in grado di rappresentare la propria gamma. –

+0

Da Delphi 1 a Delphi 2, il tipo intero è cambiato da 2 byte a 4. Dato che è il tipo intero generico, mi aspetto che aumenti di nuovo, sebbene Embarcadero possa mantenerlo 4 byte. Le enumerazioni utilizzano la dimensione più piccola adatta a tutti i valori, ma puoi specificare una dimensione minima per i tipi di enumerazione utilizzando {$ Z1} o {$ Z2} o {$ Z4} {$ MINENUMSIZE 1} o {$ MINENUMSIZE 2} o {$ MINENUMSIZE 4}. Penso che potrebbero aggiungere anche {$ Z8}. Questo è legato ai record (impacchettati) e al loro allineamento dei campi del record. –

+10

@Workshop Alex - Sono nella squadra del compilatore Emabarcadero Delphi; fidati di me quando dico che Integer resterà a 32-bit :) –

2

A parte l'ovvio puntatore < -> int compiti: (usando IntPtr/nativeint/PtrInt etc)

  • Tutto ciò che avete come un blob binario (DLL forse OCX ecc) che devono essere aggiornati. Ciò potrebbe includere vecchi SDK per chiavette, ecc.
  • Tutti gli strumenti che eseguono operazioni a livello binario (debugger, profiler, strumenti domestici del telefono) potrebbero richiedere aggiornamenti.
  • Quasi tutti assemblatore e altri trucchi molto basso livello (ad esempio, dipende dal layout di VMT, formato di debug (traceback) stub carico dinamici come in Jedi Apilib ecc) deve essere aggiornato
  • controllo Le tue intestazioni create per i cambiamenti nella imballaggio e errori di traduzione che importa ora puntatore <> intero. Il bit di imballaggio non deve essere sottostimato
  • L'interfaccia con Office e altre app esterne potrebbe cambiare
  • TComponent.tag è ora un longint e quindi potrebbe rimanere longint, il che significa che gli schemi che inseriscono i puntatori in component.tag potrebbero non funzionare.
  • x87 FPU è obsoleto su x64 e in generale SSE2 verrà utilizzato per il punto di viraggio. così il punto di virgola mobile e la sua gestione delle eccezioni potrebbero funzionare in modo leggermente diverso, e l'estensione potrebbe non essere a 80-bit (ma a 64-bit o, meno probabile, a 128-bit). Questo si riferisce anche al solito arrotondamento (coprocontrollo) cambia quando si interfaccia con il codice C che si aspetta una diversa parola fpu.

Il problema del packing dei record è qualcosa che ho notato durante il porting di intestazioni esistenti su win64.

+0

A meno che non si verifichi qualche incompatibilità imprevista, TComponent .Tag dovrebbe quasi certamente diventare NativeInt. –

+0

FPC lasciato longint –

+0

Curioso: qualsiasi metrica su (a) quante applicazioni create con FPC si basavano su Tag per fare riferimento a un oggetto e (b) si rompeva con una destinazione a 64 bit? –

80

Primo, un disclaimer: anche se lavoro per Embarcadero. Non posso parlare per il mio datore di lavoro. Quello che sto per scrivere è basato sulla mia opinione su come dovrebbe funzionare un ipotetico Delphi a 64 bit, ma possono esserci o meno opinioni contrastanti e altre incompatibilità o eventi previsti o imprevisti che causano decisioni progettuali alternative.

Detto:

  • Esistono due tipi interi, nativeint e NativeUInt, la cui dimensione sarà float compreso tra 32 bit e 64 bit in base alla piattaforma. Sono stati in giro per un bel po 'di versioni. Nessun altro tipo di numero intero cambierà la dimensione a seconda del testimone del bersaglio.

  • Assicurarsi che qualsiasi luogo che si basa su un valore colata puntatore a un intero o viceversa utilizza nativeint o NativeUInt per l'intero tipo. TComponent.Tag dovrebbe essere NativeInt nelle versioni successive di Delphi.

  • Suggerirei non utilizzare NativeInt o NativeUInt per valori basati su puntatore non. Cerca di mantenere semanticamente il codice tra 32 e 64 bit. Se hai bisogno di 32 bit di intervallo, usa Integer; se hai bisogno di 64 bit, usa Int64. In questo modo il tuo codice dovrebbe funzionare allo stesso modo su entrambi i testimoni. Solo se stai eseguendo il cast verso e da un valore di Puntatore di qualche tipo, come un riferimento o un THandle, dovresti usare NativeInt.

  • Utilizzare PByte per l'aritmetica del puntatore, se possibile, preferibilmente a NativeInt o NativeUInt. Sarà sufficiente per la maggior parte degli scopi, ed è più tipicamente sicuro perché non può essere (facilmente) scambiato per un normale tipo intero, e viceversa.

  • cose Pointer-come dovrebbero seguire regole simili ai puntatori: oggetto riferimenti (ovviamente), ma anche cose come HWND, THandle, ecc

  • Non fare affidamento sui dettagli interni di stringhe e array dinamici , come i loro dati di intestazione.

  • nostra politica generale sui cambiamenti API per 64 bit dovrebbe essere di mantenere la stessa API tra 32 bit e 64 bit, ove possibile, anche se ciò significa che API a 64 bit non necessariamente sfruttare della macchina. Per esempio , TList probabilmente gestirà solo gli elementi MaxInt div SizeOf (Pointer) , al fine di mantenere Count, indici ecc. Come numero intero. Dal momento che il tipo intero non viene spostato (ovvero le dimensioni cambiano in base al bitness), noi non vogliamo avere effetti a catena sul codice cliente: qualsiasi indice che sia tondo attraverso una variabile tipizzata Integer o for-loop index, verrebbe troncato e potenzialmente potrebbe causare bug sottili.

  • Dove API sono estesi a 64 bit, saranno molto probabilmente essere fatto con un extra di funzione/metodo/proprietà per accedere ai dati in più, e questo API saranno sostenute anche in 32-bit. Ad esempio, la routine standard standard restituirà probabilmente i valori di tipo Integer per gli argomenti della stringa di tipo o della matrice dinamica; se si vuole trattare con array dinamici molto grandi , potrebbe esserci anche una routine LongLength(), la cui implementazione a 32 bit è uguale a Length(). Length() genererebbe un'eccezione a 64 bit se applicata a un array dinamico con più di 2^32 elementi .

  • correlati a questo, ci sarà probabilmente il controllo degli errori per operazioni restringimento lingua migliorata, in particolare restringendo a 64 bit Valori posizioni a 32-bit. Ciò comporterebbe l'usabilità di assegnare il valore di ritorno di Lunghezza a Length a località di tipo Integer se Length(), ha restituito Int64. D'altra parte, specificamente per le funzioni di compiler-magic come Length(), ci può essere qualche vantaggio della magia presa, ad es. cambia il tipo di ritorno in base al contesto. Ma il vantaggio non può essere preso in modo simile in API non magiche.

  • Gli array dinamici probabilmente supporteranno l'indicizzazione a 64 bit. Si noti che gli array Java sono limitati all'indicizzazione a 32 bit, anche su piattaforme a 64 bit.

  • Le stringhe probabilmente saranno limitate all'indicizzazione a 32 bit. Abbiamo un periodo difficile con per motivi realistici per le persone che desiderano stringhe da 4 GB + che sono realmente stringhe e non solo blob gestiti di dati, per i quali gli array dinamici possono servire altrettanto bene.

  • Forse un assemblatore incorporato, ma con restrizioni, come non essere in grado di mescolare liberamente con il codice Delphi; ci sono anche regole relative alle eccezioni e al layout dello stack frame che devono essere seguite su x64.

+17

Ahi, che nessun assemblatore mi farà molto male. Ho un sacco di codice SSE nelle mie app di visione. Sì, lo so, probabilmente dovrò modificarli con i regs push/popping in x86_64, ma un aggiornamento piuttosto che trovare una soluzione diversa. –

+0

"Length() genererebbe un'eccezione a 64 bit se applicata a un array dinamico con più di 232 elementi." Umm ... 232? –

+6

@Marco: +1. Nessun ASM farà davvero del male a molte persone. –

1

I miei 2 centesimi:

  • ai vecchi tempi ogni scrittore asm doveva spinto a UTILIZZARE BASM

  • asm64 esterno sarebbe accettabile e utilizzando il vecchio xy.obj inlclude codice, mentre è necessaria una completa riscrittura

  • Debugger & CPU64: la domanda sarà questo ancora lì ??

  • D64 Float Extended: è ancora mantenuto come galleggiante a 80 bit?

Hp

4

Molte domande simili è stato chiesto quando è stato annunciato che Delphi 2009 creerebbe solo applicazioni Unicode. Alla fine si è scoperto che la maggior parte del codice esistente funzionava perfettamente senza modifiche. Le parti ingannevoli erano codice che supponeva che SizeOf(Char) = 1 e componenti di terze parti potessero farlo.

Mi aspetto che il passaggio a Delphi a 64 bit sia un'esperienza simile. Tutto funziona appena fuori dalla scatola, ad eccezione del codice che gioca con i puntatori e presuppone che sia SizeOf(Pointer) = 4 o SizeOf(Pointer) = SizeOf(Integer). È già possibile risolvere tali problemi oggi chiamando SizeOf(Pointer) anziché codice fisso 4 e utilizzando NativeInt o NativeUInt quando sono necessari numeri interi a puntatore.

Si dovrebbe usare SizeOf(Pointer) piuttosto che SizeOf(NativeInt) se si desidera che il codice per lavorare con Delphi 2007 Delphi 2007 ha una sfortunata bug che causa SizeOf(NativeInt) di restituire 8 invece di 4 come dovrebbe. Questo è stato risolto in Delphi 2009.

+0

Ho eseguito la trasformazione in Unicode abbastanza velocemente, ma comunque c'erano – Petra

+0

alcune modifiche: tutte le IORoutine (reset, readln, rewrite, writeln) per la lettura e la scrittura sui file non funzionano più per Unicode, in ogni procedura che scrive stringhe appropriate Il carattere Unicode dovrebbe essere possibile selezionare.Ma nel complesso la transizione è avvenuta abbastanza agevolmente. – Petra