* * * *

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.
Maggio 01, 2024, 04:46:30 pm

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

264 Visitatori, 1 Utente

Autore Topic: Come assicurarsi del corretto rilascio delle risorse  (Letto 14945 volte)

luigi67

  • Newbie
  • *
  • Post: 25
  • Karma: +0/-0
Come assicurarsi del corretto rilascio delle risorse
« il: Marzo 05, 2014, 01:28:43 pm »
Salve
Come da titolo, come faccio ad assicurarmi che tutte le risorse "figlie" sono correttamente rilasciate prima della della distruzione di una risorsa genitore?.
Mi spiego meglio ho una finestra principale in cui c'è una griglia collegata ad un database oggetto TDataModule che contiene svariati oggetti

TIBConnection, TIBDatabase, TFBLDatabase,
TSQLTransaction, TIBTransaction, TFBLTransaction
 TSQLQuery, TIBTable, TFBLMetadata,TRxMemoryData e
TDatasource

Se faccio un inserimento di dati e poi chiudo la finestra, rilasciando con free la relativa risorsa mi da un errore che non riesco ad intercettare con il debug, ma che mi fa pensare ad un incorretto rilascio delle risorse del datamodule, dato che se non faccio alcun inserimento, apro e richiudo l'applicazione, le risorse sono rilasciate correttamente. Se utilizzo un pulsante con "dati.Free;" e poi chiudo l'applicazione si chiude correttamente, se invece inserisco nell'evento "on close" dell'applicazione  sempre dati.Free; mi da errore.
Vorrei sapere se c'0è modo di conoscere in fase di chiusura se ci sono ancora risorse "figlie" allocate e rilasciare di conseguenza.
Grazie
Luigi

luigi67

  • Newbie
  • *
  • Post: 25
  • Karma: +0/-0
Re:Come assicurarsi del corretto rilascio delle risorse
« Risposta #1 il: Marzo 05, 2014, 01:43:33 pm »
mi correggo anche nel caso di utilizzo di dati.free, al momento della chiusura mi da l'errore, quindi non credo sia legato al datamodule ma ad un errato rilascio delle risorse l'errore che mi dà è

classe 'External: SIGSEGV'.

xinyiman

  • Administrator
  • Hero Member
  • *****
  • Post: 3249
  • Karma: +12/-0
Re:Come assicurarsi del corretto rilascio delle risorse
« Risposta #2 il: Marzo 05, 2014, 03:00:10 pm »
Riesci a darci un sorgente di prova? Detto così potrebbe essere qualunque cosa.
Ieri è passato, domani è futuro, oggi è un dono...

luigi67

  • Newbie
  • *
  • Post: 25
  • Karma: +0/-0
Re:Come assicurarsi del corretto rilascio delle risorse
« Risposta #3 il: Marzo 05, 2014, 03:18:22 pm »
ci provo, vi do la parte che mi pare incriminata,

Questo è l'avvio del programma


program trattamenti;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Interfaces, // this includes the LCL widgetset
  Forms, rxnew, sdflaz, rx, lazdbexport, ibexpress, zcomponent, zvdatetimectrls,
  fortes324forlaz, appforms, principale, ModuloDati, memo, repprod, reptrattam,
  repvisteid, repviste, messaggioiniz,FileUtil,comune,sysutils,XMLConf,LCLType;

{$R *.res}

begin
RequireDerivedFormResource := True;
Application.Initialize;
WorkDir:= ExtractFilePath(Application.ExeName);
comune.XMLConfigAppl:=TXMLConfig.Create(XMLConfigAppl);
comune.XMLConfigAppl.Filename:=WorkDir+fileImpost;
comune.DatabaseName:=XMLConfigAppl.GetValue('Dati/DatabaseName','DataBaseName');
if FileExistsUTF8(string (comune.DatabaseName)) then
   begin
   Application.CreateForm(TDati, Dati);
   Application.CreateForm(TFPrincipale, FPrincipale);
    end
  else
      begin
      MsgIni:=TMsgIni.Create(Application);
      mresult:=MsgIni.ShowModal;
      MsgIni.Free;
      if ((mresult=IDOK) or (mresult=IDYES)) then
         begin
        Application.CreateForm(TDati, Dati);
        Application.CreateForm(TFPrincipale, FPrincipale);
         end
      else
         begin
         Application.Terminate;
         end;
      end;
  Application.Run;
 end.
                           

e questa è la chiusura della finestra principale


procedure TFPrincipale.FormClose(Sender: TObject; var CloseAction: TCloseAction
  );
begin
if (DBGrPiante.DataSource.DataSet.State in dsEditModes) then
   begin
   CloseAction:=Chiusura(DBGrPiante.DataSource.DataSet);
   end
else if  (DBGrTipo.DataSource.DataSet.State in dsEditModes) then
    begin
    CloseAction:=Chiusura(DBGrTipo.DataSource.DataSet);
    end
else if (DBGrProdotti.DataSource.DataSet.State in dsEditModes)then
     begin
     CloseAction:=Chiusura(DBGrProdotti.DataSource.DataSet);
     end
else if (DBGrTrattamenti.DataSource.DataSet.State in dsEditModes) then
     begin
     CloseAction:=Chiusura(DBGrTrattamenti.DataSource.DataSet);
     end
else
    begin
    CloseAction:=caFree;
    end;
   if CloseAction=caFree then
      begin
      SalvaImpostazioni;
      Dati.TRPrincipale.Commit;
      end;
end;

procedure TFPrincipale.SalvaImpostazioni;
begin
comune.XMLConfigAppl.SetValue('Application/WorkDir',WorkDir);
comune.XMLConfigAppl.Flush;
comune.XMLConfigAppl.Free;
end;


ho provato ad aprire e chiudere da console senza fare alcuna operazione e il risultato della console è il seguente

Heap dump by heaptrc unit
283876 memory blocks allocated : 45059990/46007960
283876 memory blocks freed     : 45059990/46007960
0 unfreed memory blocks : 0
True heap size : 1114112
True free heap : 1114112


mentre se faccio qualche operazione sul database e e poi chiudo

Heap dump by heaptrc unit
359575 memory blocks allocated : 49749830/50878464
359567 memory blocks freed     : 49749678/50878296
8 unfreed memory blocks : 152
True heap size : 1245184
True free heap : 1244416
Should be : 1244504
Call trace for block $B5965340 size 16
An unhandled exception occurred at $005EA636:
EAccessViolation:
  $005EA636



ho Voluto lanciarla da console con il debug abilitato per capire se è un problema dell'ide e a quanto sembra no è un errore di rilasio delle risorse. Boh!


xinyiman

  • Administrator
  • Hero Member
  • *****
  • Post: 3249
  • Karma: +12/-0
Re:Come assicurarsi del corretto rilascio delle risorse
« Risposta #4 il: Marzo 05, 2014, 03:27:52 pm »
Intendo proprio tutto il sorgente zippato. Così lo debuggo e vedo se riesco ad aiutarti.
Ieri è passato, domani è futuro, oggi è un dono...

luigi67

  • Newbie
  • *
  • Post: 25
  • Karma: +0/-0
Re:Come assicurarsi del corretto rilascio delle risorse
« Risposta #5 il: Marzo 05, 2014, 03:45:28 pm »
scusa, ma come faccio ad aggiungere il file zip?
« Ultima modifica: Marzo 05, 2014, 03:48:15 pm da luigi67 »

nomorelogic

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2871
  • Karma: +20/-4
Re:Come assicurarsi del corretto rilascio delle risorse
« Risposta #6 il: Marzo 05, 2014, 05:47:19 pm »
quando rispondi, appena sotto il "Memo" in cui scrivi, c'è un link che devi espandere: "Allegati ed altre opzioni"
Imagination is more important than knowledge (A.Einstein)

luigi67

  • Newbie
  • *
  • Post: 25
  • Karma: +0/-0
Re:Come assicurarsi del corretto rilascio delle risorse
« Risposta #7 il: Marzo 05, 2014, 06:01:31 pm »
Allora credo di aver scoperto il problema è dovuto al fatto che uso una lista a puntatori e non rilascio la memoria.
Ho un oggetto di questo tipo


PProdotti=^TProdotti;
 TProdotti=record
   pianta:string;
   IDprodotto:string;
   quantita:single;
   next:PProdotti;


allocato dinamicamente con  con



function TFPrincipale.CaricaRecTrattamenti(var numpiante:integer):PProdotti;
var
ProdPrimo,Prodotti,ProdCorrente,ProdPrecedente:PProdotti;
PPiante:PPianta;
begin
   try
   dati.TTempTrattamenti.First;
   Prodotti:=CaricaProdotti;
   ProdPrimo:=Prodotti;
   PPiante:=CaricaPiante;
   dati.TTempTrattamenti.DisableControls;
   ProdPrecedente:=Nil;
   new(ProdCorrente);
   numpiante:=0;
   Result:=ProdCorrente;
   while PPiante<>nil do
      begin
      inc(numpiante,1);
      while Prodotti<>Nil do
         begin
         if ProdPrecedente=nil then
            begin
            ProdCorrente^.pianta:=PPiante^.pianta;
            ProdCorrente^.IDprodotto:=Prodotti^.IDprodotto;
            ProdCorrente^.quantita:=Prodotti^.quantita;
            ProdPrecedente:=ProdCorrente;
            end
       else
           begin
           ProdPrecedente:=ProdCorrente;
            new(ProdCorrente);
            ProdCorrente^.pianta:=PPiante^.pianta;
            ProdCorrente^.IDprodotto:=Prodotti^.IDprodotto;
            ProdCorrente^.quantita:=Prodotti^.quantita;
            ProdPrecedente^.next:=ProdCorrente;
            end;
         ProdCorrente^.next:=Nil;
         Prodotti:=Prodotti^.next;
      end;
   Prodotti:=ProdPrimo;
   PPiante:=PPiante^.next;
   end;
   finally
   dati.TTempTrattamenti.EnableControls;
   end;
end;
                                       


ma come vedi nella procedura Non c'è il rilascio della memoria!! :-\
per rilasciare la memoria come faccio ripercorro la lista e vado rilasciando la memoria o basta fare un dispose di ProdPrimo?

nomorelogic

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2871
  • Karma: +20/-4
Re:Come assicurarsi del corretto rilascio delle risorse
« Risposta #8 il: Marzo 05, 2014, 06:14:13 pm »
ciao, l'argomento è già stato affrontato, dai un'occhiata a questo 3D
http://www.lazaruspascal.it/index.php?topic=1244.msg6743#msg6743
Imagination is more important than knowledge (A.Einstein)

luigi67

  • Newbie
  • *
  • Post: 25
  • Karma: +0/-0
Re:Come assicurarsi del corretto rilascio delle risorse
« Risposta #9 il: Marzo 05, 2014, 08:46:25 pm »
Allora ho due alternative o vado cancellando nodo per noto oppure uso un'allocazione iniziale della dimensione che mi serve conoscendo il numero dei record con getmen
.........
numrecord:=contarecord
GetMem(recPointer, numrecord * SizeOf(TRecord));
 e alla fine
freemen(recPointer, numrecord * SizeOf(TRecord));
 rifacendomi all'esempio
http://www.delphibasics.co.uk/RTL.asp?Name=GetMem&ExpandCode1=Yes#Ex1

e così non ci dovrebbe essere più la necessità di usare le liste o sbaglio?
Altra domanda dato che uso una funzione che restituisce un puntatore devo rilasciare la memoria usata dalle variabili di tipo PProdotti all'interno della funzione e poi riguardo alla funzione stessa che restituisce un result di tipo  PProdotti? una volta rilasciata la memoria della lista si dovrebbe rilasciare anche quella della funzione giusto?
Ciao
Luigi

Stilgar

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2382
  • Karma: +10/-0
Re:Come assicurarsi del corretto rilascio delle risorse
« Risposta #10 il: Marzo 06, 2014, 09:38:01 am »
O Mamma.
Ma usare gli oggetti?
In questo modo non è l'utilizzatore che gestisce la memoria ma direttamente l'oggetto.
Mi piego.
".Create"
".Destroy"
servono a questo.
Se hai una catena di oggetti, basta che in ".Destroy" metti il codice che elimina il prossimo nodo.
Codice: [Seleziona]
if assigned(next) then
  FreeAndNil(FNext);
due righe semplici semplici.
Poi saranno affari del gestore dello heap a rilasciare correttamente la ram ;)


Codice: [Seleziona]
TProdotto = class(TObject)
protected
   FPianta:string;
   IDProdotto:string;
   FQuantita:single;
   FNext:TProdotto;
public
  Constructor Create;
  Destructor Destroy; override;
published
  property Pianta: String;
  property Quantita : Single;
  Next : TProdotto;
end;

....

Constructor TProdotto.Create;
Begin
   FPianta:='';
   IDProdotto:='';
   FQuantita:=0.0;
   FNext:=nil;
End;

Destructor TProdotto.Destroy;
Begin
   FPianta:='';
   IDProdotto:='';
   FQuantita:=0.0;
  if Assigned(FNext) then FreeAndNil(FNext);
  inherited Destroy;
End;

....

La butto lì senza nemmeno passare per l'ide ;)

Stilgar[/code]
Al mondo ci sono 10 tipi di persone ... chi capisce il binario e chi no.

nomorelogic

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2871
  • Karma: +20/-4
Re:Come assicurarsi del corretto rilascio delle risorse
« Risposta #11 il: Marzo 06, 2014, 10:17:20 am »
premetto che ci sono mooooolte alternative all'uso delle liste di puntatori, alternative che gestiscono bene la memoria senza impazzire (ad esempio open array e le liste di oggetti come suggerito da Stilgar)


Allora ho due alternative o vado cancellando nodo per noto oppure uso un'allocazione iniziale della dimensione che mi serve conoscendo il numero dei record con getmen

esatto
(oppure usi gli open array come detto sopra ;) )

Altra domanda dato che uso una funzione che restituisce un puntatore devo rilasciare la memoria usata dalle variabili di tipo PProdotti all'interno della funzione e poi riguardo alla funzione stessa che restituisce un result di tipo  PProdotti?

se ti riferisci a
ProdPrimo,Prodotti,ProdCorrente,ProdPrecedente:PProdotti;PPiante:PPianta;

lo spazio per le variabili dichiarate nella sezione "var" sono allocate in memoria al lancio della procedura/funzione e sono deallocate immediatamente dopo il termine di questa
e questo a prescindere dal loro contenuto

quindi: no



una volta rilasciata la memoria della lista si dovrebbe rilasciare anche quella della funzione giusto?

in che senso?
la funzione quando termina su autorilascia
Imagination is more important than knowledge (A.Einstein)

luigi67

  • Newbie
  • *
  • Post: 25
  • Karma: +0/-0
Re:Come assicurarsi del corretto rilascio delle risorse
« Risposta #12 il: Marzo 06, 2014, 11:19:59 am »
Ragazzi siete veramente in gamba! Credo che adotterò la soluzione di Stilgar, mi sembra la più elegante e assolve al mio scopo che non è sviluppare un'applicazione. Si non è questo  il mio vero scopo. Sto sviluppando questa applicazione per rimparare a programmare.
In pratica sto riprendendo dopo anni di inattività, sono rimasto a Delphi 7, completamente dimenticato.
Ho scoperto Lazarus per caso e vi devo dire è stato amore a prima vista sopratutto perché open e supportato da tanto materiale che si trova in rete e forum come questo!
Io di mestiere sono un Network manager e il mio sistema operativo principe è Linux nella versione Centos  che conosco abbastanza bene, di conseguenza lazarus! su linux!
Ok adesso per puro esercizio accademico come dicevo prima volevo allocare la memoria che mi serve e po de-allocarla questo un frammento di codice ripreso dalla pagina delphi



 in cosa sbaglio? in pratica alloco la quantità di memoria necessaria e
function TFPrincipale.CaricaProdotti(var numprod:integer):PProdotti;
var
i:integer;
mempos:string;
prod:PProdotti;
begin
try
i:=1;
dati.TTempTrattProdotti.Filtered:=true;
dati.TTempTrattProdotti.First;
Result:=Nil;
numprod:= THackGrid(DBGRTrattProdotti).VisibleRowCount;
Getmem(prod,numprod*SizeOf(TProdotti) );//alloco la memoria necessaria
for i := 1 to numprod do
begin
prod^. IDprodot:=dati.TTempTrattProdotti.FieldByName('Prodotto').AsString; //quì mi da errore
dati.TTempTrattProdotti.Next;
Inc(Result);
end;
........



ho notato che in delphi l'assegnazione è differente


begin
  // Allocate storage for three records
  // Note : It is better to use New for this
  // It is used here for illustration purposes only
  GetMem(recPointer, 3 * SizeOf(TRecord));

  // Fill out these 3 records with values
  recPointer.name := 'Brian';  //io invece devo usare "^." perché?
  recPointer.age  := 23;

  Inc(recPointer);
  recPointer.name := 'Jim';
  recPointer.age  := 55;

  Inc(recPointer);
  recPointer.name := 'Sally';
  recPointer.age  := 38;

  // Now display these values
  Dec(recPointer, 2);
  ShowMessageFmt('%s is %d',[recPointer.name, recPointer.age]);
  Inc(recPointer);
  ShowMessageFmt('%s is %d',[recPointer.name, recPointer.age]);
  Inc(recPointer);
  ShowMessageFmt('%s is %d',[recPointer.name, recPointer.age]);
end;

luigi67

  • Newbie
  • *
  • Post: 25
  • Karma: +0/-0
Re:Come assicurarsi del corretto rilascio delle risorse
« Risposta #13 il: Marzo 06, 2014, 12:25:44 pm »
Allora rifacendomi all'esempio di Stilgar ho creato per maggiore chiarezza una unit in cui creo due oggetti: eccovi di seguito il codice

unit oggetti;

{$mode objfpc}{$H+}{$M+}

interface

uses
   Classes, SysUtils;
type

{ TPianta }

TPianta=class(TObject)
private
 procedure SetNomePianta(AValue: String);
protected
FNomePianta:string;
Fnext:TPianta;
public
  Constructor Create;
  Destructor Destroy; override;
published
  Next : TPianta;
  property NomePianta: String read FNomePianta write SetNomePianta;
   end;

{ TProdotto }

TProdotto = class(TObject)
private
   procedure SetIDProdotto(AValue: String);
   procedure SetNomePianta(AValue: String);
   procedure SetQuantita(AValue: Single);
protected
   FNomePianta:string;
   FIDProdotto:string;
   FQuantita:single;
   FNext:TProdotto;
public
  Constructor Create;
  Destructor Destroy; override;
published
  Next : TProdotto;
  property NomePianta: String read FNomePianta write SetNomePianta;
  property IDProdotto: String read FIDProdotto write SetIDProdotto;
  property Quantita : Single read FQuantita write SetQuantita;

 end;


implementation

{ TPianta }

procedure TPianta.SetNomePianta(AValue: String);
begin
   if NomePianta=AValue then Exit;
   FNomePianta:=AValue;
end;


constructor TPianta.Create;
begin
 FNomePianta:='';
end;

destructor TPianta.Destroy;
begin
  FNomePianta:='';
  if Assigned(FNext) then FreeAndNil(FNext);
  inherited Destroy;
end;


{ TProdotto}
procedure TProdotto.SetNomePianta(AValue: String);
begin
   if FNomePianta=AValue then Exit;
   FNomePianta:=AValue;
end;

procedure TProdotto.SetIDProdotto(AValue: String);
begin
   if FIDProdotto=AValue then Exit;
   FIDProdotto:=AValue;
end;



procedure TProdotto.SetQuantita(AValue: Single);
begin
   if FQuantita=AValue then Exit;
   FQuantita:=AValue;
end;


constructor TProdotto.Create;
Begin
   FNomePianta:='';
   IDProdotto:='';
   FQuantita:=0.0;
   FNext:=nil;
End;

destructor TProdotto.Destroy;
Begin
   FNomePianta:='';
   IDProdotto:='';
   FQuantita:=0.0;
  if Assigned(FNext) then FreeAndNil(FNext);
  inherited Destroy;
End;
end.


Vi chiedo come faccio a caricare i dati su qesti oggetti, caipisco che devo usare le properti per assegnare i valori alle singole voci es:


PProdotto: TProdotto
PProdotto:=TProdotto.create(self);
PProdotto.IDProdotto:='123';
......
per il record successivi al primo come faccio, devo richiamare pprodotto.next.idprodotto? Mi manca un passaggio
Grazie
Luigi

Stilgar

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2382
  • Karma: +10/-0
Re:Come assicurarsi del corretto rilascio delle risorse
« Risposta #14 il: Marzo 06, 2014, 12:49:34 pm »
Codice: [Seleziona]
TProdotto.create(self);
Qui non compila.
Per il resto sei sulla strada giusto :D

Questa catena la devi gestire alla vecchia maniera. Tieni solo il primo oggetto referenziato. Poi sono affari suoi gestire il resto della catena.
Se vuoi farlo più ficaccione il codice :
Codice: [Seleziona]
property  Next : TProdotto read getNext write setNext;

Codice: [Seleziona]
procedure TProdotto.setNext(value: TProdotto);
begin
  if Assigned(fNext) then fNext.Next := Value
  else
    FNext := Value;
end;

In questo modo ottieni "gratis" la ricerca della coda. Metti l'ultimo next alla fine della catena.

Aggiungi che sfrutti lo stack per la ricerca della posizione. Meno cicli for e while ;)
Solo un if e un call.

Stilgar
Al mondo ci sono 10 tipi di persone ... chi capisce il binario e chi no.

 

Recenti

How To

Utenti
Stats
  • Post in totale: 18784
  • Topic in totale: 2236
  • Online Today: 465
  • Online Ever: 900
  • (Gennaio 21, 2020, 08:17:49 pm)
Utenti Online
Users: 1
Guests: 264
Total: 265

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.