Libérer un tableau dynamique de Tstrings à 2 dimensions

Résolu
Caribensila Messages postés 2527 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 16 octobre 2019 - 27 janv. 2009 à 19:37
f0xi Messages postés 4205 Date d'inscription samedi 16 octobre 2004 Statut Modérateur Dernière intervention 12 mars 2022 - 28 janv. 2009 à 13:52
Bonjour,




J'ai besoin d'une structure de données un peu particulière : un tableau dynamique à 2 dimensions de TStringList. Mais je me demande comment libérer tout ça?
Ce tableau n'est pas rectangulaire, donc pour le déclarer, je fais comme ça :



var TestArray : array of array of  TStrings;
      i, j : Integer;



begin
  {Je dimensionne le 1er tableau :}
  SetLength(TestArray,3,0);
  {Je dimensionne les cellules :}
  SetLength(TestArray[0],1);
  SetLength(TestArray[1],2);
  SetLength(TestArray[2],1);
  {Je remplis le tableau :}
  TestArray[0,0] := TStringList.Create;
  TestArray[1,0] := TStringList.Create;
  TestArray[1,1] := TStringList.Create;
  TestArray[2,0] := TStringList.Create;
  {Ici, j'utilise mon tableau. Par exemple :}
  TestArray[0,0].Add('Test 1');
  TestArray[1,0].Add('Test 2');

  ...




  {Libération des TStringList :}

  for i := 0 to Length(TestArray)-1 do begin
    for j := 0 to Length(TestArray[i])-1 do begin
      TestArray[i,j].Free; // Je libère les TStringList.
    end;
  end;



    {Libération du tableau :}
  Finalize(TestArray); // <- Est-ce bien suffisant???



Voila. Je me demande s'il ne faudrait pas libérer tous les tableaux de chaque cellule?
Merci pour vos lumières.
Cari

9 réponses

f0xi Messages postés 4205 Date d'inscription samedi 16 octobre 2004 Statut Modérateur Dernière intervention 12 mars 2022 35
28 janv. 2009 à 13:52
faut que je pense a approfondire mes exemples :

Type
  TMachin = pointer;
  TMyArrays = array of array of TMachin

var
  MyArrays = TMyArrays;

memoire occupée par MyArrays :

4 bytes

allocation :

SetLength(MyArrays, 2);

memoire occupée :

(2 * 4) bytes

allocation :

SetLength(MyArray[0], 10);
SetLength(MyArray[1], 5);

memoire occupée :

68 bytes

allocation :

for N := 0 to 9 do
  case N of
    0..4 : begin
             New(MyArrays[0,N]);
             New(MyArrays[1,N]);
           end;
    5..9 :  New(MyArrays[0,N];
  end;

memoire occupée :

128 bytes

désalocation :

for N := 9 downto 0 do
  case N of
    0..4 : begin
             Dispose(MyArrays[1,N]);
             Dispose(MyArrays[0,N]);
           end;
    5..9 : Dispose(MyArrays[0,N]);
  end;
SetLength(MyArrays[1], 0);
SetLength(MyArrays[0], 0);
SetLength(MyArrays, 0);

autre possibilité :

type
  TMyArrays = array of array of TMachin;
  pMyArrays = ^TMyArrays;

var
  ptr : pMyArrays;

allocation :
  New(ptr);
  SetLength(ptr^, 2);
  SetLength(ptr^[0], 10);
  SetLength(ptr^[1], 5);

désalocation :
  SetLength(ptr^[0], 0);
  SetLength(ptr^[1], 0);
  SetLength(ptr^, 0);
  Dispose(ptr);

a savoir aussi que toute variable, constante font au minimum 5 bytes :

[pointeur 4 byte] [type char 1 bytes]

exemple :

var
  MonInt : integer;
  MonString : string;
  MonPointeur : ^byte;

memoire occupée par MonInt = 2*4 bytes
memoire occupée par MonString = (2*4)+1 bytes en UTF8 et (2*4)+2 bytes en UTF16
memoire occupée par MonPointeur non alloué (new) = 2*4 bytes
memoire occupée par MonPointeur alloué  (new) = (2*4)+1 bytes
memoire occupée par MonPointeur assignée sur var existante = 2*4 bytes

3
Bacterius Messages postés 3792 Date d'inscription samedi 22 décembre 2007 Statut Membre Dernière intervention 3 juin 2016 10
27 janv. 2009 à 19:50
Les tableaux dynamiques n'ont pas besoin d'être libérés.

Extrait de l'aide Delphi :

"Les références aux tableaux dynamiques sont comptées et ces tableaux se libèrent automatiquement quand il ne font plus l'objet d'aucune référence."

Il n'y a pas besoin de libérer un tableau dynamique, il s'auto-libère.
Au pire, un Finalize doit être suffisant :

Extrait de l'aide de Delphi (Finalize) :

"Les tableaux dynamiques ne peuvent jamais être désalloués à l'aide de la procédure Dispose, mais vous pouvez les libérer en les transmettant à Finalize."

Mais il est également indiqué que (ça peut peut-être t'aider) : "Dans les cas où plusieurs variables sont désallouées dans un bloc de mémoire contiguë tel qu'un tableau de chaînes alloué dynamiquement, le paramètre additionnel Count peut être spécifié afin de finaliser toutes les variables en une seule opération."

En tout cas moi je n'ai jamais libéré mes tableaux dynamiques conformément à l'aide Delphi - après, ma mémoire vive est une déchetterie peut-être à cause de ça ?

Cordialement, Bacterius !
0
Utilisateur anonyme
27 janv. 2009 à 19:56
Salut,

Je comprend pas trop ta question : tu as un seul tableau qui contient différentes cellules. A chaque cellule est rattachée une StringList. Donc

1)Etape 1 : initialisation du tableau //Initialize
2)Etape 2 : dimensionnement du tableau //SetLength
3)Etape 3 : Création de la StringList de chaque cellule  // TStringList.Create
4)Etape 4 :Utilisation des StringList //Add
5)Etaoe 5 : Destruction des StringList // Free
6)Etape 6 : Finalisation du tableau // Finalize

Je vois pas trop ce que l'on peut faire de plus

Mais te connaissant, j'ai du louper un épisode : M'sieur si vous plait, possible de rentrer dans votre vortex cyto-neuronal pour connaitre votre pensée ? (Je te connais mon grand : ta question cache autre chose . M'sieur Cari nous avons les moyens de vous faire parler )
0
Caribensila Messages postés 2527 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 16 octobre 2019 18
27 janv. 2009 à 20:18
@Bacterius

En fait, j'ai toujours eu un doute avec ces foutus tableaux dynamiques!

Extrait de l'Aide :
«Pour libérer un tableau dynamique, affectez nil à une variable qui référence le tableau ou transmettez la variable à Finalize»

@Francky  
Regarde bien la déclaration :



array of array of  TStrings;


En fait, c'est un tableau à 1 dimension dont chaque cellule contient un tableau de TStrings.
Ou alors, j'ai encore compris queud' 
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Caribensila Messages postés 2527 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 16 octobre 2019 18
27 janv. 2009 à 20:59
re@Francky
Je cite M. Beaulieu :

« Avec les tableaux dynamiques multidimentionnels, on est plus proche de ceci :

array[0..2] of array[0..1] of TStrings;

que de cela :

array[0..2, 0..1] of TStrings; »

D'où mon doute...


[mailto:re@Bacterius
re@Bacterius
]


1) Il est possible que les tableaux dynamiques soient désalloués sur le destroy... Mais en attendant, tu te trimballes tes tableaux jusque la fin de l'application. D'où l'intérêt de pouvoir les libérer à la main... 
C'est peut-être une explication au manque de clarté de l'aide...

2) «Dans les cas où plusieurs variables sont désallouées dans un bloc de mémoire contiguë ...»

        - Et à qui je dois demander si c'est le cas ou pas?  lolll
0
Caribensila Messages postés 2527 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 16 octobre 2019 18
27 janv. 2009 à 21:21
Finalement, je vais faire comme ça, c'est plus sûr :

{Libération des TStringList :}
  for i := 0 to Length(TestArray)-1 do begin
    for j := 0 to Length(TestArray[i])-1 do begin
      TestArray[i,j].Free; // Je libère les TStringList.
    end;
  end;




  {Libération des tableaux}

 
for i := 0 to Length(TestArray)-1 do begin
    Finalize(TestArray[i]);
  end;
  Finalize(TestArray);

En tout cas ça passe! Et comme en plus je suis dans une de mes classes, je préfère ne pas prendre de risque...

Merci pour vos réponses, les gars!
0
f0xi Messages postés 4205 Date d'inscription samedi 16 octobre 2004 Statut Modérateur Dernière intervention 12 mars 2022 35
27 janv. 2009 à 22:46
avec les tableaux dynamique :

type
  TMyArray = array of TMachin;

var MyArray : TMyArray;

memoire occupée :

4 octet

reservation de memoire :

SetLength(MyArray, X);

memoire occupée :

4 + (X * Taille de TMachin)

liberation de la memoire :

SetLength(MyArray, 0);

memoire occupée :

4 octet

0
Utilisateur anonyme
27 janv. 2009 à 23:39
MonTableau : array[0..2] of array[0..1] of TMachin;

: Pourtant on utilise bien l'expression de tableau multidimentionnel et non de tableau de tableau. Si Beaulieu a raison cela implique que quelque soit le TMachin il faut libérer tout les sous tableaux et non juste MonTableau. Donc ta question dépasse le cadre du TStringList : Voila une question intéressente. Je savais que cela cachait autre chose .
0
Caribensila Messages postés 2527 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 16 octobre 2019 18
28 janv. 2009 à 01:57
Bein oui... Les TStringList, on sait bien qu'il faut les libérer.

Mais un tableau dynamique n'est pas comparable à un tableau statique. Ils sont liés à la notion de pointeurs. D'où la taille de 4 octets quand on les déclare (taille d'un pointeur) comme le montre très bien f0xi.

Mais quid d'un tableau de tableaux?
Je pense qu'il faut faire comme j'ai montré et ne pas compter sur l'auto-libération. D'ailleurs je me suis tj demandé qui était le owner d'un tableau (l'application?).

Je pense que l'expression de tableau multidimentionnel quand il s'agit d'un tableau dynamique est une façon de cacher son reel fonctionnement pour le confort du programmeur. Comme souvent, Delphi nous cache l'utilisation des pointeurs. 
C'est sans doute plus confortable, mais il faut quand même en avoir conscience.
C'est pas parce que ça s'utilise de ma même façon que c'est kif-kif !

Enfin, c'est ce que je pense pour le moment...  :)
0
Rejoignez-nous