* * * *

Privacy Policy

Blog italiano

Clicca qui se vuoi andare al blog italiano su Lazarus e il pascal.

Forum ufficiale

Se non siete riusciti a reperire l'informazione che cercavate nei nostri articoli o sul nostro forum vi consiglio di visitare il
Forum ufficiale di Lazarus in lingua inglese.

Lazarus 1.0

Trascinare un file nel programma
DB concetti fondamentali e ZeosLib
Recuperare codice HTML da pagina web
Mandare mail con Lazarus
Stabilire il sistema operativo
Esempio lista in pascal
File INI
Codice di attivazione
Realizzare programmi multilingua
Lavorare con le directory
Utilizzare Unità esterne
TTreeView
TTreeview e Menu
Generare controlli RUN-TIME
LazReport, PDF ed immagini
Intercettare tasti premuti
Ampliare Lazarus
Lazarus e la crittografia
System Tray con Lazarus
UIB: Unified Interbase
Il file: questo sconosciuto
Conferma di chiusura di un applicazione
Liste e puntatori
Overload di funzioni
Funzioni a parametri variabili
Proprietà
Conversione numerica
TImage su Form e Panel
Indy gestiore server FTP lato Client
PopUpMenu sotto Pulsante (TSpeedButton)
Direttiva $macro
Toolbar
Evidenziare voci TreeView
Visualizzare un file Html esterno
StatusBar - aggirare l'errore variabile duplicata
Da DataSource a Excel
Le permutazioni
Brute force
Indy 10 - Invio email con allegati
La gestione degli errori in Lazarus
Pascal Script
Linux + Zeos + Firebird
Dataset virtuale
Overload di operatori
Lavorare con file in formato JSON con Lazarus
Zeos ... dietro le quinte (prima parte)
Disporre le finestre in un blocco unico (come Delphi)
Aspetto retrò (Cmd Line)
Lazarus 1.0
Come interfacciare periferica twain
Ubuntu - aggiornare free pascal e lazarus
fpcup: installazioni parallele di lazarus e fpc
Free Pascal e Lazarus sul Raspberry Pi
Cifratura: breve guida all'uso dell'algoritmo BlowFish con lazarus e free pascal.
Creare un server multithread
guida all'installazione di fpc trunk da subversion in linux gentoo
Indice
DB concetti fondamentali e connessioni standard
Advanced Record Syntax
DB concetti fondamentali e DBGrid
DB concetti fondamentali e TDBEdit, TDBMemo e TDBText
Advanced Record Syntax: un esempio pratico
Superclasse form base per programmi gestionali (e non)
Superclasse form base per programmi gestionali (e non) #2 - log, exception call stack, application toolbox
Superclasse form base per programmi gestionali (e non) #3 - traduzione delle form
Superclasse form base per programmi gestionali (e non) #4 - wait animation
Un dialog per la connessione al database:TfmSimpleDbConnectionDialog
Installare lazarus su mac osx sierra
immagine docker per lavorare con lazarus e free pascal
TDD o Test-Driven Development
Benvenuto! Effettua l'accesso oppure registrati.
Novembre 25, 2024, 10:25:25 pm

Inserisci il nome utente, la password e la durata della sessione.

48 Visitatori, 0 Utenti

Autore Topic: Il peso dei record  (Letto 2369 volte)

sanric

  • Newbie
  • *
  • Post: 20
  • Karma: +0/-0
    • RiccardoSantato.net
Il peso dei record
« il: Luglio 24, 2023, 06:07:23 pm »
Salve a tutti, è la prima volta che vi chiedo qualcosa ma sono molto "niubbo" e non riesco a venirne fuori da questa semplice cosa.  ;)
Se scrivo il seguente programma...

Codice: [Seleziona]
program unRecord;
uses SysUtils;

type
  iMieiDati = record
    nome:string;   //8 bytes
    cognome:string;   //8 bytes
    dataDiNascita:TDateTime; // 8 bytes
    case vivente:Boolean of //1 byte
      True: (residenza:string[20]);  //20 bytes
      False: (dataDecesso:TDateTime); //8 bytes
  end;

var
  imperatore:iMieiDati;

begin
  with imperatore do
    begin
      nome:='Napoleone';
      cognome:='Bonaparte';
      dataDiNascita:=EncodeDate(1769,8,15);
      vivente:=False;
      dataDecesso:=EncodeDate(1821,5,5);
    end;

  WriteLn('Il record pesa ',sizeof(imperatore),' bytes.');
end.

e lo eseguo, nel mio sistema a 64 bit, risulta che:
Codice: [Seleziona]
Il record pesa 56 bytes.

Ora, accanto ad ogni singola variabile, ho segnato in commento il valore che di essa mi viene fornito tramite il comando sizeof().
Da qui la domanda: perché il valore usato nell'esempio è 56 e non 33?
Non ho usato tutti i campi ma mi pare che vengano allocati lo stesso da FPC: ad esempio la variabile residenza viene allocata lo stesso anche nel caso in cui il case... of si riveli falso.
Se volessi essere sicuro che il compilatore non vada ad usare più memoria del necessario, come posso fare?

Beh, mi sembra che come primo approccio ci sia abbastanza carne al fuoco.
Grazie mille a tutti per le gentili risposte.

PS: ho fatto la stessa domanda sia a Bard che a ChatGPT. Ne è risultato che i limiti di quelle tecnologie sono davvero tanti.
Tanto per dire, Bard è rimandato a settembre in matematica dal momento che è convinto che
Codice: [Seleziona]
Pertanto, la dimensione totale del record è 4 + 4 + 8 + 20 + 8 = 56 byte.
  ;D

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1405
  • Karma: +44/-0
  • Prima ascoltare, poi decidere
Re:Il peso dei record
« Risposta #1 il: Luglio 24, 2023, 09:06:44 pm »
Ciao, quello che dici è vero se prima di "record" ci aggiungi la parolina "packed" ... ;D

Tutte le strutture vengono riempite con dei "pad" cioè del byte nulli (a zero) per allineare i dati.
Questo operazione consente di ottimizzare il codice compilato ed è praticamente obbligatorio per avere un codice veloce.

Se è presente "packed" allora il compilatore non inserirà alcun "pad" e il record verrà gestito in maniera integrale.

[OT]
Il modo di riempimento (cioè la posizione dei pad) non può essere previsto in maniera assoluta, anche se ci sono delle regole, e ciò fà si che l'uso dei PUNTATORI E DELLA LORO MATEMATICA per l'accesso generico al record può generare inconvenienti difficili da prevedere e da diagnosticare.

Questo è uno dei motivi per cui "odio" l'uso dei puntatori espliciti con le variabili.

Ciao
« Ultima modifica: Luglio 24, 2023, 09:15:02 pm da DragoRosso »
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1405
  • Karma: +44/-0
  • Prima ascoltare, poi decidere
Re:Il peso dei record
« Risposta #2 il: Luglio 24, 2023, 09:11:56 pm »
Il record pesa 56 bytes.
PS: ho fatto la stessa domanda sia a Bard che a ChatGPT. Ne è risultato che i limiti di quelle tecnologie sono davvero tanti.
Tanto per dire, Bard è rimandato a settembre in matematica dal momento che è convinto che
Codice: [Seleziona]
Pertanto, la dimensione totale del record è 4 + 4 + 8 + 20 + 8 = 56 byte.
  ;D

Bard (ma il suo compare non è da meno) è l'esempio tipico della AI: ciò che riportano magari è anche giusto, ma non si sà il perchè ....  ;)
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

sanric

  • Newbie
  • *
  • Post: 20
  • Karma: +0/-0
    • RiccardoSantato.net
Re:Il peso dei record
« Risposta #3 il: Luglio 25, 2023, 07:12:43 am »
Ciao, quello che dici è vero se prima di "record" ci aggiungi la parolina "packed" ... ;D

Tutte le strutture vengono riempite con dei "pad" cioè del byte nulli (a zero) per allineare i dati.
[cut]

Grazie mille DragoRosso per la gentile risposta.
Quindi non è del tutto vero che le variabili che fanno parte della "variant part" (così vengono definite nell'Object Pascal Language Guide di Borland) non sono allocate preventivamente. O sbaglio?

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1405
  • Karma: +44/-0
  • Prima ascoltare, poi decidere
Re:Il peso dei record
« Risposta #4 il: Luglio 25, 2023, 08:01:32 am »
Le parti "variant" dei record sono allocate preventivamente sulla lunghezza più lunga dei campi interessati, in realtà ci pensa il compilatore.

I record hanno sempre lunghezza fissa, perchè le definizioni che hanno lunghezza variabile (ad esempio una "string") vengono allocate come puntatore. La "lunghezza" di un record non cambia durante la vita dello stesso.

Per inserire i "pad", il compilatore si basa sull'allineamento predefinito (in un 64 bit l'allineamento è a 64 bit, ossia quad word o 8 byte) o l'allineamento in essere in quella parte di codice.

Quindi, supponiamo che l'allineamento predefinito non venga modificato allora qualsiasi variabile (campo) di un record viene allineato a quella lunghezza o suoi multipli inserendo dei byte a zero. Questo in generale. Ogni compilatore può usare una propria tecnica per il riempimento.

Ciao
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

sanric

  • Newbie
  • *
  • Post: 20
  • Karma: +0/-0
    • RiccardoSantato.net
Re:Il peso dei record
« Risposta #5 il: Luglio 26, 2023, 07:00:22 am »
Approfitto della vostra gentilezza per comprendere qualcosa che davvero mi sfugge e cioè: perché le "variant parts" di una struttura record, pur avendo un'istruzione condizionale al proprio interno, non la rispettano?
Faccio un piccolo esempio qui sotto:

Codice: [Seleziona]
program variantPart;

type
  TPersona = record
    nome:string;
    cognome:string;
    dataDiNascita:TDateTime;
    case vivente:Boolean of
      True: (residenza:string[20]);
      False: (dataDecesso:TDateTime);
  end;

var
  imperatore:TPersona;

begin
  with imperatore do
  begin
    nome:='Napoleone';
    cognome:='Bonaparte';
    vivente:=False;
    residenza:='Parigi';  \\ <----
  end;
  WriteLn(imperatore.nome,' ',imperatore.cognome);
  WriteLn('Residenza: ',imperatore.residenza);
end.

In teoria, essendo per l'appunto Napoleone morto da un bel pezzo, la variabile residenza non dovrebbe essere contemplata ed il compilatore avrebbe dovuto darmi un bel messaggio d'errore.
Invece tutto fila liscio come l'olio con il seguente output:

Codice: [Seleziona]
Napoleone Bonaparte
Residenza: Parigi

Logicamente mi sembra che la cosa non torni: dove mi sto sbagliando?

nomorelogic

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2921
  • Karma: +20/-4
Re:Il peso dei record
« Risposta #6 il: Luglio 26, 2023, 09:51:57 am »
ciao sanric

il fatto è che la parti varianti del record, condividono la memoria e questo è il motivo per cui sono stati implementati.
Questo in modo da permettere di vedere quella parte di memoria come un campo unico oppure come più campi.

Sta a chi codifica utilizzare il record variante in modo congruo.
Nel tuo caso tramite una "if" potresti decidere quale variante utilizzare.

Leggi qua per maggiori spiegazioni.
https://wiki.freepascal.org/Record#Variable_structure
Imagination is more important than knowledge (A.Einstein)

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1405
  • Karma: +44/-0
  • Prima ascoltare, poi decidere
Re:Il peso dei record
« Risposta #7 il: Luglio 26, 2023, 10:45:13 am »
Per completare quanto detto da @nomorelogic, la memoria condivisa (che come ti accennavo è lunga quanto la lunghezza massima del campo più lungo + eventuali pad) è diciamo in formato raw. Cosa significa ?

Significa che inserendo una stringa nel campo residenza o un data nel campo datadecesso ciò che "leggerai" usando entrambe le variabili sarà congruo solo ed esclusivamente se leggerai il campo corretto.

Se inserisci una data (il cui formato interno è un double) tale valore potrà essere riletto correttamente solo se accederai al dato "datadecesso", idem per la residenza. E fai attenzione che leggendo ad esempio la "datadecesso" avendo inserito come ultimo dato una stringa in "residenza" potrebbe provocare una eccezione (perchè un double ha una rappresentazione ben precisa e quindi potrebbe essere generato un NAN ... "not a number").

Nel tuo esempio hai inserito il valore "Parigi" come residenza, prova e leggere il campo "datadecesso" e vedi cosa ti riporta ...

Ciao
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

sanric

  • Newbie
  • *
  • Post: 20
  • Karma: +0/-0
    • RiccardoSantato.net
Re:Il peso dei record
« Risposta #8 il: Luglio 27, 2023, 07:09:43 am »

Nel tuo esempio hai inserito il valore "Parigi" come residenza, prova e leggere il campo "datadecesso" e vedi cosa ti riporta ...

Ho fatto la prova: FPC mi ha restituito il valore "30/12/99", quasi fosse una sorta di valore di default.
Mah, forse chi ha costruito FPC ha ascoltato molto Prince!  ;D

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1405
  • Karma: +44/-0
  • Prima ascoltare, poi decidere
Re:Il peso dei record
« Risposta #9 il: Luglio 27, 2023, 10:26:44 am »
Ho fatto la prova: FPC mi ha restituito il valore "30/12/99", quasi fosse una sorta di valore di default.
Mah, forse chi ha costruito FPC ha ascoltato molto Prince!  ;D

 :D In realtà quella è la rappresentazione in formato datetime della stringa che hai inserito (non ho notizia che 30/12/99 sia un qualche default).

Giusto per dire che con le parti variant dei dati occorre fare molta attenzione. Io in genere preferisco inserire un campo che definisce il tipo di dato rappresentato in un altro campo (anche variant, anche se non mi piace molto) in modo che sia inequivocabile la cosa, e con l'accesso protetto sia in lettura che in scrittura tale per cui l'errore è pressochè impossibile.

Ti posto appena possibile un esempio di codice.

Ciao
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

sanric

  • Newbie
  • *
  • Post: 20
  • Karma: +0/-0
    • RiccardoSantato.net
Re:Il peso dei record
« Risposta #10 il: Luglio 27, 2023, 10:56:12 am »

Ti posto appena possibile un esempio di codice.

Grazie mille, sono in debito!

nomorelogic

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2921
  • Karma: +20/-4
Re:Il peso dei record
« Risposta #11 il: Luglio 27, 2023, 03:33:39 pm »
Ho fatto la prova: FPC mi ha restituito il valore "30/12/99", quasi fosse una sorta di valore di default.
Mah, forse chi ha costruito FPC ha ascoltato molto Prince!  ;D

 :D In realtà quella è la rappresentazione in formato datetime della stringa che hai inserito (non ho notizia che 30/12/99 sia un qualche default).

30/12/99 in effetti suona strano
me se fosse 30/12/1899 (e probabilmente lo è) allora sarebbe un valore per rappresentare una data zero
potrebbe essere che, non essendo presente nell'area di memoria, una data valida, venga restituito 30/12/1899


Edit:
potresti verificare la data esatta formattando tipo "yyyy-mm-dd"?
Imagination is more important than knowledge (A.Einstein)

sanric

  • Newbie
  • *
  • Post: 20
  • Karma: +0/-0
    • RiccardoSantato.net
Re:Il peso dei record
« Risposta #12 il: Luglio 27, 2023, 03:57:53 pm »

potresti verificare la data esatta formattando tipo "yyyy-mm-dd"?

Ok, ho fatto la prova usando questo codice (più che altro un recap se qualche niubbo come me si fosse perso nel frattempo):

Codice: [Seleziona]
program variantPart;

uses
  SysUtils, DateUtils;

type
  TPersona = record
    nome:string;
    cognome:string;
    dataDiNascita:TDateTime;
    case vivente:Boolean of
      True: (residenza:string[20]);
      False: (dataDecesso:TDateTime);
  end;

var
  imperatore:TPersona;

begin
  with imperatore do
  begin
    nome:='Napoleone';
    cognome:='Bonaparte';
    vivente:=False;
    residenza:='Parigi';  // <----
    WriteLn(nome,' ',cognome);
    WriteLn('Residenza: ',residenza);
    WriteLn(FormatDateTime('yyyy-mm-dd',dataDecesso));
  end;
end.

Il risultato è codesto (e avevi ragione tu):

Codice: [Seleziona]
Napoleone Bonaparte
Residenza: Parigi
1899-12-30

Come sospettato, sembra essere un valore di default per indicare una data "0", in modo da non incappare nel rischio ipotizzato da DragoRosso di un NaN.
Se così fosse mi sembrerebbe una mossa intelligente.


nomorelogic

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2921
  • Karma: +20/-4
Re:Il peso dei record
« Risposta #13 il: Luglio 27, 2023, 04:00:57 pm »
essendo così, quella data del 1899 la puoi usare come costante per verificare se è presente un valore oppure no
Imagination is more important than knowledge (A.Einstein)

sanric

  • Newbie
  • *
  • Post: 20
  • Karma: +0/-0
    • RiccardoSantato.net
Re:Il peso dei record
« Risposta #14 il: Luglio 27, 2023, 04:14:04 pm »
Certo, sapendolo posso gestire la cosa abbastanza comodamente con un ciclo if.. then.

Tuttavia, anche se ho compreso le spiegazioni fornite, trovo il fatto di allocare lo stesso la memoria per le variabili comprese in una variant-part un po' fuorviante.
Se non fossero allocate sarebbe più logico e semplice poter effettuare un controllo in fase di parsing del codice, evitando errori.
Inoltre, se il padding è il vero problema, non comprendo perché non poter utilizzare anche nelle variant-part dei puntatori "mascherati" (ad es. string al posto di string[xxx]).

Vabbé, mi fermo qui altrimenti la cosa diventa pesante e non so quanto interessante per gli altri utenti del forum.

 

Recenti

How To

Utenti
  • Utenti in totale: 803
  • Latest: maXim.FI
Stats
  • Post in totale: 19198
  • Topic in totale: 2289
  • Online Today: 68
  • Online Ever: 900
  • (Gennaio 21, 2020, 08:17:49 pm)
Utenti Online
Users: 0
Guests: 48
Total: 48

Disclaimer:

Questo blog non rappresenta una testata giornalistica poiché viene aggiornato senza alcuna periodicità. Non può pertanto considerarsi un prodotto editoriale ai sensi della legge n. 62/2001.