Limite StringGrid?

Résolu
jlmcom Messages postés 57 Date d'inscription mercredi 4 août 2004 Statut Membre Dernière intervention 3 décembre 2004 - 10 oct. 2004 à 19:01
jlmcom Messages postés 57 Date d'inscription mercredi 4 août 2004 Statut Membre Dernière intervention 3 décembre 2004 - 14 oct. 2004 à 10:48
Bonjour,

1. Est-ce que quelqu'un connaît la limite de capacité d'un StringGrid ?
J'ai voulu charger dans ce composant un fichier de plus de 1 Mo et me sort une erreur d'exception EoutofMemory (mémoire insuffisante).
2. Ou bien est-ce un problème de RAM ?
J'ai une Ram de 64 Mo. Je sais ! C'est riquiqui ! mais je dois changer mon portable dans deux mois !
3. Dans ce dernier cas, y a t?il des delphimans qui peuvent m?indiquer le code permettant de réserver cette mémoire avant que ça ne plante le programme ?
Merci d'avance.

A titre d'indication, voici le corps de ma procédure pour charger les caractères du fichier sans type.

procedure TFormMemoireFic.VoirMemoireHexa(Filename : String);
var
fS : TFileStream;
li, co : Integer;
octet : string ;
begin
fS:= TFileStream.Create(filename, fmOpenRead or fmShareDenyWrite);
try
fS.Position := 0;
StringGrid1.RowCount := fS.Size div 16+1;
?
{Chargement fichier dans StringGrid ligne par ligne regroupant 16 octets}
for li := 1 to StringGrid1.RowCount do
begin
?
fS.Read(octet[1], 16);
?
end;
finally
fS.Free;
end;
end;

jlmcom

8 réponses

cs_Delphiprog Messages postés 4297 Date d'inscription samedi 19 janvier 2002 Statut Membre Dernière intervention 9 janvier 2013 32
11 oct. 2004 à 09:51
Dans l'aide en ligne de Delphi, il n'est fait mention d'aucune limitation du nombre de lignes pour le composant TStringGrid.

Comme je ne comprends rien à ton code et notamment comment tu affectes du contenu aux cellules du composant TStringGrid, voici un code qui fonctionne, même avec seulement 64 Mo de mémoire vive je pense :
procedure TForm1.Button2Click(Sender: TObject);
var
  fs: TFileStream;
  Buffer: array[0..15] of char;
  i: integer;
begin
  fs :=  TFileStream.Create('data.dat', fmOpenRead or fmShareDenyWrite);
  try
    //détermination du nombre de lignes nécessaires
    i := fs.Size mod SizeOf(Buffer);
    if i = 0 then
      StringGrid1.RowCount := fs.Size div SizeOf(Buffer)
    else
      StringGrid1.RowCount := fs.Size div SizeOf(Buffer) + 1;
    fs.Position := 0;
    i := 1;
    //découpage du flux en tranches de SizeOf(Buffer) caractères
    while fs.Read(Buffer, SizeOf(Buffer)) <> 0 do
    begin
      StringGrid1.Cells[1, i] := Buffer;
      inc(i);
    end;
  finally
    FreeAndNil(fs);
  end;

end;


Pensez à cliquer sur Réponse acceptée lorsque la réponse vous convient.
3
jlmcom Messages postés 57 Date d'inscription mercredi 4 août 2004 Statut Membre Dernière intervention 3 décembre 2004 2
12 oct. 2004 à 14:49
Bonjour delphiprog !

Je réponds à ton précédent message et te fais part de mes dernières investigations :

1. En fait ce que je veux c'est 1 caractère par cellule. C'est vrai qu'au début, dans mon exemple je parle de blocs, mais c'est parce que je pensai séparer la lecture par bloc pour éviter trop d'accès disque de l'écriture dans les cellules. C'est vrai maintenant qu'avec le P IV ! Je gère pour l'instant le projet avec P II avec 64Mo Ram.

2. Voici le code du test que tu m?a communiqué auquel j'ai ajouté un test sur le n° de ligne pour afficher les différentes valeurs de la mémoire ::


procedure TForm1.Charger(nom : String);
var Fs : TFileStream;   Buf : array[0..15] of char;  L,C : Integer;
begin
  fs := TFileStream.Create(nom, fmOpenRead or fmShareDenyWrite);
  try
    fs.Position := 0;
    L := fs.Size mod SizeOf(Buf);
    if  L = 0 then StringGrid1.RowCount := fs.Size div SizeOf(Buf)
                  else StringGrid1.RowCount := fs.Size div SizeOf(Buf) + 1;
    fs.Position := 0;
    L := 1;
    while fs.Read(Buf, SizeOf(Buf)) <> 0 do
    begin
      {Adresse de la ligne dans la 1ère colonne}
      AdrLigneStr := IntToHex(16*(l-1),8);
      Insert(':', AdrLigneStr, 5);
      StringGrid1.Cells[0,l] := AdrLigneStr;      
      {écriture cellule}
      For C := 1 to 15 do StringGrid1.Cells[C, L] := Buf[C];
      inc(L);
      if L > 1000 then {valeur de ligne pour stopper le programme en mode débug}
      begin
        Mem.dwLength:=SizeOf(TMemoryStatus);
        GlobalMemoryStatus(Mem);
        showmessage('Mem Phy Tot  = '+FloatToStrF(Mem.dwTotalPhys/1024,ffFixed,5,1)+' Ko'+#13#10
          +'Mem Phy Lib  = '+FloatToStrF(Mem.dwAvailPhys/1024,ffFixed,5,1)+' Ko'+#13#10
          +'Mem Pag Tot  = '+FloatToStrF(Mem.dwTotalPageFile/1024/1024,ffFixed,5,1)+' Mo'+#13#10
          +'Mem Pag Lib  = '+FloatToStrF(Mem.dwAvailPageFile/1024/1024,ffFixed,5,1)+' Mo'+#13#10
          +'Mem Vir Tot  = '+FloatToStrF(Mem.dwTotalVirtual/1024/1024,ffFixed,5,1)+' Mo'+#13#10
          +'Mem Vir Lib  = '+FloatToStrF(Mem.dwAvailVirtual/1024/1024,ffFixed,5,1)+' Mo');
      end;    
  end;{while}
  finally
    FreeAndNil(fs);
  end;
end;


3 : Le programme après la 20007 ème ligne lorsqu'il sur le début de la boucle :
while fs.Read(Buf, SizeOf(Buf)) <> 0 do
Les mémoires totales ne bougent pas. Elles sont de :

Mem Physique totale : 65 024 Ko
Mem Paginée totale : 101,8 Mo
Mem Virtuelle totale : 2 044,0 Mo
Les mémoires libres équivalentes sont appellées respectivement : Phy, Pag, Virt

Arrêt au Nombre de ligne =
0 100 5000 20001
Phy : 2 980 Ko 22 468 Ko 12 004,0 Ko :question) 0,0 Ko
Pag : 519,0 Mo 27,1 Mo 17,1 Mo 1,7 Mo
Virt :2 011,8 Mo 2 011,8 Mo 2 007,8 Mo 1 992,8 Mo

Je m?attendais à ce que ça plante avec la RAM = 0,0 Ko, mais non, il y a un jeu d'échange entre la mémoire paginée et la mémoire physique (Ram je suppose !).
Pour info, c'est toujours intéressant de voir comment ça fonctionne, voici les évolutions de ces mémoires jusqu'au plantage :L 20001> Phy = 0 => Pag = 1,7L 20002> Phy = 452 => Pag = 1,6L 20003> Phy = 420 => Pag = 1,6L 20004> Phy = 392 => Pag = 1,6L 20005> Phy = 420 => Pag = 1,5L 20006> Phy = 616 => Pag = 1,5L 20007> Phy = 1 112 => Pag = 1,5L 20008> Plantage

4. Mon diagnostic est que c'est la RAM et la mémoire paginée qui sont insuffisante. Comment calculer si j'ai assez de mémoire ? La directive de compilation agit elle sur la mémoire paginée libre ?

Si tu as du code pour le calcul de la mémoire nécessaire?
Merci
jlmcom :)
3
florenth Messages postés 1023 Date d'inscription dimanche 1 août 2004 Statut Membre Dernière intervention 17 août 2008 3
12 oct. 2004 à 18:49
Bonjour,

Ce que tu peux faire pour ne pas saturer la memoire c'est utiliser la classe TProcessFileStream que tu trouveras ici .
C'est tres bien expliqué et c'est tres facile à manier.

De plus, comme le tutorial le dit, tu pourras traiter des fichiers de plusieurs gigas (perso je me suis arrete à 200 mO) sans faire planter ton pc.

Evidemment il faut utiliser la methode ChunkByChunk ... sinon cela ne sert à rien.

Sinon pour allouer de la memoire, je ne connais que la directive de compilation {$MINSTACKSIZE nombre} où nombre est en Ko

Florent

Si tu ne te plantes pas ......
tu ne poussera jamais
3
jlmcom Messages postés 57 Date d'inscription mercredi 4 août 2004 Statut Membre Dernière intervention 3 décembre 2004 2
11 oct. 2004 à 18:50
Merci delphiprog!

J'ai implanté ta procédure. Mais ça marche pas! ?-) J'ai donc un problème de mémoire.
La grille est créee avec toutes les cellules, mais dès que
je cherche à remplir les cellules, ça plante.

Comment faire? Peut-être que le streamémory gère mieux la mémoire?

Ce que je veux, c'est afficher chaque caractère dans une grille.
Le but est que l'utilisateur peut sélectionner un espace de caractères (contigus) ou bien un en particulier.

Pas évident d'être clair, en effet! Le grisé du code n'avait pas fonctionné, je ne sais pourquoi!

Merci pour tonaide.

jlmcom
0

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

Posez votre question
cs_Delphiprog Messages postés 4297 Date d'inscription samedi 19 janvier 2002 Statut Membre Dernière intervention 9 janvier 2013 32
11 oct. 2004 à 19:05
Si tu utilises un TMemoryStream, ça risque d'être pire. Tu devras alors utiliser :
1- un TFileStream pour la lecture du fichier
2- un TMemoryStream pour transférer le contenu du TFileStream en mémoire
3- faire une copie des données dans la grille de chaînes

Comme tu vois, ça ne peut pas arranger le problème...

Peux-tu faire une exécution en pas à pas et me dire où ça plante exactement ?

Je ne suis pas sûr d'avoir bien compris : tu veux charger caractère par caractère ou par blocs de 16 caractères les cellules du TStringGrid ?

Pensez à cliquer sur Réponse acceptée lorsque la réponse vous convient.
0
jlmcom Messages postés 57 Date d'inscription mercredi 4 août 2004 Statut Membre Dernière intervention 3 décembre 2004 2
13 oct. 2004 à 11:01
Merci Florenth

1. :approve) Très intéressant ce code! Je vais étudier cela de plus près.

2. %-6 Alzamer! La directive $MINSTACKSIZE concerne la pile je crois? Est-ce qu'il y a un rapport entre la pile et la mémoire physique directement? si si je me souviens bien, je ne crois pas!
Dans le code, je n'ai pas géré de pile, c'est le Stram qui gère ou windows!?

3. :clown) Dans mon diagnostique, j'ai l'impression de m'être planté. En effet, ce que j'ai appelé mémoire physique (utilisation de Mem.dwAvailPhys) est bien la mémoire physique du disque et non la RAm comme je l'avais supposé.

Ce qui m'a induit en erreur, c'est sa valeur de départ (65 024 Ko) qui est proche de 64 Mo Ram de ma config! Mais après vérif, il me restait bien cette place sur le disque. il est temps de changer d'ordinateur! J'ai viré quelques Mo et ça a fonctionné!

4. :question) J'ai encore une possibilité à exploiter, puisqu'il s'agit de la mémoire disponible sur le disque. Avant de lancer l'opération, je devrais pouvoir calculer la mémoire dont j'ai besoin. A priori, je ne comprends pas, car mon fichier fait 1,3 mo à peu près ce qui est loin de 65 Mo.

jlmcom 8-)
0
florenth Messages postés 1023 Date d'inscription dimanche 1 août 2004 Statut Membre Dernière intervention 17 août 2008 3
13 oct. 2004 à 16:16
Âïe aïe aïe !! Autant pour moi .. :clown) Tu as bien raison, la directive $MINSTACKSIZE concerne bien les piles ...

Désolé pour cette (stupide ??) erreur.

Sinon le code que je t'ai donne (enfin l'adresse) fonctionne tres bien.

:question) Tu veux calculer la memoire dont tu as besoin sur le disque ???? Pour quoi faire ? J'avoue que je ne comprends rien à ce qu tu raconte dans ton paragraphe 3 .

Enfin , l'important est de trouver d'où cela vient ..... et que cela marche !! :-p .

@ ++

Florent

Si tu ne te plantes pas ......
tu ne poussera jamais
0
jlmcom Messages postés 57 Date d'inscription mercredi 4 août 2004 Statut Membre Dernière intervention 3 décembre 2004 2
14 oct. 2004 à 10:48
Bonjour florenth

1. Merci pour ton intérêt. bon, on sature et on est tous nul à certains moments. Je me replonge sur ces questions de mémoire, j'en suis encore aux vieux concepts.

2. Bon, je ne vais éterniser ma question du début qui était pourqoui ça bloquait avec le stringgrid qui n'était pas en cause. J'en ai trouver la réponse. Alors je devrais répondre satsisfaisant dès que j'ai compris mon problème. je valide donc vos réponses aux personnes qui m'ont répondu : florenth, delphiprog et moi-même, sympha non?

3. :question) Pour la question de la mémoire, cela devrait faire l'objet d'une autre question sur le forum, non ? Qu'en penses les administrateurs? j'apprends en même temps le fonctionnement de ce forum.
Delphiprog va être content, si si il aime pas s'éterniser sur des questions qui en emmène d'autres...

4. Pour répondre rapidement au point 3 de mon précédent message. il me faut faire la différence entre la gestion de la pile (variables dynamiques) et mémoire physique (écriture disque).

5. Merci en tout cas à vous deux! Je travaille sur le sujet et recontacte le forum si besoin. Car j'ai encore du menage à faire dans mes vieilles approches (BP 7) avec winprocs, omemory etc...

jlmcom
0
Rejoignez-nous