|
begin process at 2008 07 05 14:05:07
Derniers logiciels
|
Trouver une ressource (Nouvelle version du moteur, plus rapide & pertinent, essayez le !)
Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum.
Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !
Sujet : Fuite mémoire avec StringGrid [ Archives / J'AI BESOIN D'AIDE !!!! :O ] (Stauf)
|
Fuite mémoire avec StringGrid
le 25/02/2002 15:57:56

Stauf
|
Bonjour, J'ai le problème suivant: Je crée dynamiquement des données puis libère l'espace une fois affichées. Jusque là, pas de soucis, l'espace est alloué puis libéré. Maintenant, je lance une fenêtre espion dans laquelle j'affiche lesdites données dans un StringGrid... et là, ça va plus : l'espace n'est plus libéré ou pas à chaque coup. Résultat, mon application grossit, grossit jusqu'à exploser la mémoire virtuelle. Là où c'est riglo, c'est quand j'iconifie mon application : Le volume mémoire pris par l'application revient à un seuil très bas. Puis si je la re-maximize, elle reprend son niveau initial puis grossit, grossit... Pour être tranquille, j'initialise le nombre de lignes de mon stringGrind à 10000 lignes. Quand j'ouvre la fenêtre, je vois bien l'alocation mémoire associée, mais rien n'y fait: La mémoire grossit alors que je n'ajoute pas de ligne : j'écris dans les 10000 premières lignes... Note : Je travaille sous Delphi 5.0 Bon, ben là j'y comprends rien !!  Merci de m'aider.
|
|
|
|
Re : Fuite mémoire avec StringGrid
le 25/02/2002 18:57:34

Delphiprog
(Admin CS)
|
Ben, personnellement, je ne chercherais pas à afficher 10000 lignes dans un stringgrid ! Les bases de données font faites pour gérer de gros volumes de données et un TDbGrid pour n'en n'afficher qu'une partie : celle qui est visible. Utiliserais-tu des tableaux dynamiques, par hasard ? Donnes un peu plus de détails si tu veux que l'on t'aide. ------------------------------- Réponse au message : ------------------------------- Bonjour, J'ai le problème suivant: Je crée dynamiquement des données puis libère l'espace une fois affichées. Jusque là, pas de soucis, l'espace est alloué puis libéré. Maintenant, je lance une fenêtre espion dans laquelle j'affiche lesdites données dans un StringGrid... et là, ça va plus : l'espace n'est plus libéré ou pas à chaque coup. Résultat, mon application grossit, grossit jusqu'à exploser la mémoire virtuelle. Là où c'est riglo, c'est quand j'iconifie mon application : Le volume mémoire pris par l'application revient à un seuil très bas. Puis si je la re-maximize, elle reprend son niveau initial puis grossit, grossit... Pour être tranquille, j'initialise le nombre de lignes de mon stringGrind à 10000 lignes. Quand j'ouvre la fenêtre, je vois bien l'alocation mémoire associée, mais rien n'y fait: La mémoire grossit alors que je n'ajoute pas de ligne : j'écris dans les 10000 premières lignes... Note : Je travaille sous Delphi 5.0 Bon, ben là j'y comprends rien !!  Merci de m'aider.
|
|
|
|
Re : Fuite mémoire avec StringGrid
le 26/02/2002 08:40:03

Stauf
|
Bon, alors allons-y pour plus de détails et merci de s'intéresser à mon problème. Je crée dynamiquement des structures dans un Thread, thread qui est chargé de faire l'acquisition de données sur une ligne série. Une fois les données collectées, je passe le pointeur de cette structure : - à une fonction de ma fenêtre espion, qui l'utilise pour remplir le StringGrid de la manière suivante : MyStringGrid.Cells[0, i] := IntToHex(p^.donnees); où MyStringGrid est le StringGrid où je veux afficher les données que je reçois chaque seconde, i, l'indice de la ligne, compris entre 1 et 10000 (pour mémoire, le stringgrid est initialisé à 10000 lignes) p le pointeru passé en paramètre de la procédure. - à un autre Thread qui se charge de différents affichages puis qui libère l'espace alloué en faisant un: p^.Free(); Dispose(p); Peut-être d'autres infos : J'initialise le StringGrid de la manière suivante: MyStringGrid.RowCount := 10000; La mémoire diminue beaucoup quand j'iconifie : Je pensais que ça aurait donc pu être dû à une sorte de mémoire vidéo alloué par Windows ? J'avoue que je débute en programmation Windows et je ne connaissais pas Delphi auparavant. J'ai repris le code existant, qui utilisait le StringGrid. Il y aurait donc des objets plus adaptés pour ce genre d'application? Je vais déjà éplucher l'aide sur les TBdGrid.... Merci. ------------------------------- Réponse au message : ------------------------------- Ben, personnellement, je ne chercherais pas à afficher 10000 lignes dans un stringgrid ! Les bases de données font faites pour gérer de gros volumes de données et un TDbGrid pour n'en n'afficher qu'une partie : celle qui est visible. Utiliserais-tu des tableaux dynamiques, par hasard ? Donnes un peu plus de détails si tu veux que l'on t'aide. ------------------------------- Réponse au message : ------------------------------- Bonjour, J'ai le problème suivant: Je crée dynamiquement des données puis libère l'espace une fois affichées. Jusque là, pas de soucis, l'espace est alloué puis libéré. Maintenant, je lance une fenêtre espion dans laquelle j'affiche lesdites données dans un StringGrid... et là, ça va plus : l'espace n'est plus libéré ou pas à chaque coup. Résultat, mon application grossit, grossit jusqu'à exploser la mémoire virtuelle. Là où c'est riglo, c'est quand j'iconifie mon application : Le volume mémoire pris par l'application revient à un seuil très bas. Puis si je la re-maximize, elle reprend son niveau initial puis grossit, grossit... Pour être tranquille, j'initialise le nombre de lignes de mon stringGrind à 10000 lignes. Quand j'ouvre la fenêtre, je vois bien l'alocation mémoire associée, mais rien n'y fait: La mémoire grossit alors que je n'ajoute pas de ligne : j'écris dans les 10000 premières lignes... Note : Je travaille sous Delphi 5.0 Bon, ben là j'y comprends rien !!  Merci de m'aider.
|
|
|
|
Re : Fuite mémoire avec StringGrid
le 26/02/2002 11:26:31

PhGORMAND
|
Salut. Je ne saisis par tout le problème, mais il y a deux choses qui me choquent : 1 - En général, pour liberer un pointeur, on utilise l'instruction NIL plutot que FREE -> P := Nil; 2 - Résever 10000 ligne d'office pour un StringGrid, est abérant. Une bonne gestion de la mémoire doit se faire de façon dynamique tant que c'est possible. Donc un StringGrid étant une collection de pointeur sur des objet de type TEdit, il est de loin préférable, de créer une nouvelle ligne seulement si on en a besoin. Ex : StringGrid1.RowCount := StringGrid1.RowCount + 1; Ou bien StringGrid1.RowCount := NbLignesFichier + 1; A+ ------------------------------- Réponse au message : ------------------------------- Bon, alors allons-y pour plus de détails et merci de s'intéresser à mon problème. Je crée dynamiquement des structures dans un Thread, thread qui est chargé de faire l'acquisition de données sur une ligne série. Une fois les données collectées, je passe le pointeur de cette structure : - à une fonction de ma fenêtre espion, qui l'utilise pour remplir le StringGrid de la manière suivante : MyStringGrid.Cells[0, i] := IntToHex(p^.donnees); où MyStringGrid est le StringGrid où je veux afficher les données que je reçois chaque seconde, i, l'indice de la ligne, compris entre 1 et 10000 (pour mémoire, le stringgrid est initialisé à 10000 lignes) p le pointeru passé en paramètre de la procédure. - à un autre Thread qui se charge de différents affichages puis qui libère l'espace alloué en faisant un: p^.Free(); Dispose(p); Peut-être d'autres infos : J'initialise le StringGrid de la manière suivante: MyStringGrid.RowCount := 10000; La mémoire diminue beaucoup quand j'iconifie : Je pensais que ça aurait donc pu être dû à une sorte de mémoire vidéo alloué par Windows ? J'avoue que je débute en programmation Windows et je ne connaissais pas Delphi auparavant. J'ai repris le code existant, qui utilisait le StringGrid. Il y aurait donc des objets plus adaptés pour ce genre d'application? Je vais déjà éplucher l'aide sur les TBdGrid.... Merci. ------------------------------- Réponse au message : ------------------------------- Ben, personnellement, je ne chercherais pas à afficher 10000 lignes dans un stringgrid ! Les bases de données font faites pour gérer de gros volumes de données et un TDbGrid pour n'en n'afficher qu'une partie : celle qui est visible. Utiliserais-tu des tableaux dynamiques, par hasard ? Donnes un peu plus de détails si tu veux que l'on t'aide. ------------------------------- Réponse au message : ------------------------------- Bonjour, J'ai le problème suivant: Je crée dynamiquement des données puis libère l'espace une fois affichées. Jusque là, pas de soucis, l'espace est alloué puis libéré. Maintenant, je lance une fenêtre espion dans laquelle j'affiche lesdites données dans un StringGrid... et là, ça va plus : l'espace n'est plus libéré ou pas à chaque coup. Résultat, mon application grossit, grossit jusqu'à exploser la mémoire virtuelle. Là où c'est riglo, c'est quand j'iconifie mon application : Le volume mémoire pris par l'application revient à un seuil très bas. Puis si je la re-maximize, elle reprend son niveau initial puis grossit, grossit... Pour être tranquille, j'initialise le nombre de lignes de mon stringGrind à 10000 lignes. Quand j'ouvre la fenêtre, je vois bien l'alocation mémoire associée, mais rien n'y fait: La mémoire grossit alors que je n'ajoute pas de ligne : j'écris dans les 10000 premières lignes... Note : Je travaille sous Delphi 5.0 Bon, ben là j'y comprends rien !!  Merci de m'aider.
|
|
|
|
Re : Fuite mémoire avec StringGrid
le 26/02/2002 11:58:20

Stauf
|
Autant pour moi : Je fais en fait : p^.free(); // Je libère la structure pointée par p Dispose (p); p:=nil; Quant au 10000 lignes, c'est une exigence du client. De toutes façons, j'ai besoin de toutes ces lignes ! Au bout de 10000 lignes, je n'ai pas trouvé d'autre moyen que de recopier les 9000 dernières lignes en haut du StringGrid, de manière à avoir dans le StringGrid au moins les 9000 dernières lignes reçues. Y a-t-il un moyen de gérer plus élégamment la mémoire ? En fait, ce qu'il me faut dans cette fenêtre espion, c'est afficher des lignes de données (les 10000 plus récentes reçues... avec une barre de défilement bien sûr) et sans perte de mémoire !!! Autre question : Comment libérer de la mémoire allouée dans un StringGrid par la propriété RowCount ? Si vous avez d'autres idées pour réaliser cela, je suis preneur... Merci ------------------------------- Réponse au message : ------------------------------- Salut. Je ne saisis par tout le problème, mais il y a deux choses qui me choquent : 1 - En général, pour liberer un pointeur, on utilise l'instruction NIL plutot que FREE -> P := Nil; 2 - Résever 10000 ligne d'office pour un StringGrid, est abérant. Une bonne gestion de la mémoire doit se faire de façon dynamique tant que c'est possible. Donc un StringGrid étant une collection de pointeur sur des objet de type TEdit, il est de loin préférable, de créer une nouvelle ligne seulement si on en a besoin. Ex : StringGrid1.RowCount := StringGrid1.RowCount + 1; Ou bien StringGrid1.RowCount := NbLignesFichier + 1; A+ ------------------------------- Réponse au message : ------------------------------- Bon, alors allons-y pour plus de détails et merci de s'intéresser à mon problème. Je crée dynamiquement des structures dans un Thread, thread qui est chargé de faire l'acquisition de données sur une ligne série. Une fois les données collectées, je passe le pointeur de cette structure : - à une fonction de ma fenêtre espion, qui l'utilise pour remplir le StringGrid de la manière suivante : MyStringGrid.Cells[0, i] := IntToHex(p^.donnees); où MyStringGrid est le StringGrid où je veux afficher les données que je reçois chaque seconde, i, l'indice de la ligne, compris entre 1 et 10000 (pour mémoire, le stringgrid est initialisé à 10000 lignes) p le pointeru passé en paramètre de la procédure. - à un autre Thread qui se charge de différents affichages puis qui libère l'espace alloué en faisant un: p^.Free(); Dispose(p); Peut-être d'autres infos : J'initialise le StringGrid de la manière suivante: MyStringGrid.RowCount := 10000; La mémoire diminue beaucoup quand j'iconifie : Je pensais que ça aurait donc pu être dû à une sorte de mémoire vidéo alloué par Windows ? J'avoue que je débute en programmation Windows et je ne connaissais pas Delphi auparavant. J'ai repris le code existant, qui utilisait le StringGrid. Il y aurait donc des objets plus adaptés pour ce genre d'application? Je vais déjà éplucher l'aide sur les TBdGrid.... Merci. ------------------------------- Réponse au message : ------------------------------- Ben, personnellement, je ne chercherais pas à afficher 10000 lignes dans un stringgrid ! Les bases de données font faites pour gérer de gros volumes de données et un TDbGrid pour n'en n'afficher qu'une partie : celle qui est visible. Utiliserais-tu des tableaux dynamiques, par hasard ? Donnes un peu plus de détails si tu veux que l'on t'aide. ------------------------------- Réponse au message : ------------------------------- Bonjour, J'ai le problème suivant: Je crée dynamiquement des données puis libère l'espace une fois affichées. Jusque là, pas de soucis, l'espace est alloué puis libéré. Maintenant, je lance une fenêtre espion dans laquelle j'affiche lesdites données dans un StringGrid... et là, ça va plus : l'espace n'est plus libéré ou pas à chaque coup. Résultat, mon application grossit, grossit jusqu'à exploser la mémoire virtuelle. Là où c'est riglo, c'est quand j'iconifie mon application : Le volume mémoire pris par l'application revient à un seuil très bas. Puis si je la re-maximize, elle reprend son niveau initial puis grossit, grossit... Pour être tranquille, j'initialise le nombre de lignes de mon stringGrind à 10000 lignes. Quand j'ouvre la fenêtre, je vois bien l'alocation mémoire associée, mais rien n'y fait: La mémoire grossit alors que je n'ajoute pas de ligne : j'écris dans les 10000 premières lignes... Note : Je travaille sous Delphi 5.0 Bon, ben là j'y comprends rien !!  Merci de m'aider.
|
|
|
|
Re : Fuite mémoire avec StringGrid
le 26/02/2002 16:19:33

PhGORMAND
|
Ce qui est bizard, c'est qu'il n'y a pas de plantage avec P^.Free; puis Dispose(P); Free est une methode d'objet qui detruit l'objet et libere la mémoire qui lui est associé. Il est précisé dans l'aide de DELPHI, qu'on ne doit pas utiliser Dispose avec Free ou Create. "Dispose" ne doit etre utilisé seulement si on a aloué de la mémoire avec "New". En principe on ne peut utiliser Free seulement avec Nil ( c'est pas obligatoire ) . Nil signifit simplement que le pointeur ne pointe sur rien, mais j'avoue que je n'ai jammais trouvé très claire les explications de l'aide. Ce que je sais pas expérience, c'est que l'on peut faire P.Free; P:=Nil; mais pas l'inverse. Free doit être utilisé avec Create et jammais avec Dispose. Dispose doit être utilisé avec New, FreeMem, GetMem. Le plantage mémoire n'est pas systématique, si on ne perturbe pas l'espace d'autres données ou d'autres objets, mais on peut imaginer les conséquences sur une grosse application. Quand à la libération mémoire d'une stringGrid. En principe, le seul fait de changer le nombre de ligne ( propriété RowCount ) alloue ou libère la mémoire automatiquement, car la propriété appelle une procédure d'allocation de mémoire ( vive la VCL ). Alors 10000 lignes pourquoi pas, mais de combien de données chacunes ? Je ne connais pas le cahier des charges de ton programme, mais le role d'un programmeur est aussi d'expliquer et de convaincre son client qu'il peut y avoir d'autre solutions (j'en sais quelque chose ) pour que cela fonctionne. A condition d'apporter une solution pratique bien sur. A+ ------------------------------- Réponse au message : ------------------------------- Autant pour moi : Je fais en fait : p^.free(); // Je libère la structure pointée par p Dispose (p); p:=nil; Quant au 10000 lignes, c'est une exigence du client. De toutes façons, j'ai besoin de toutes ces lignes ! Au bout de 10000 lignes, je n'ai pas trouvé d'autre moyen que de recopier les 9000 dernières lignes en haut du StringGrid, de manière à avoir dans le StringGrid au moins les 9000 dernières lignes reçues. Y a-t-il un moyen de gérer plus élégamment la mémoire ? En fait, ce qu'il me faut dans cette fenêtre espion, c'est afficher des lignes de données (les 10000 plus récentes reçues... avec une barre de défilement bien sûr) et sans perte de mémoire !!! Autre question : Comment libérer de la mémoire allouée dans un StringGrid par la propriété RowCount ? Si vous avez d'autres idées pour réaliser cela, je suis preneur... Merci ------------------------------- Réponse au message : ------------------------------- Salut. Je ne saisis par tout le problème, mais il y a deux choses qui me choquent : 1 - En général, pour liberer un pointeur, on utilise l'instruction NIL plutot que FREE -> P := Nil; 2 - Résever 10000 ligne d'office pour un StringGrid, est abérant. Une bonne gestion de la mémoire doit se faire de façon dynamique tant que c'est possible. Donc un StringGrid étant une collection de pointeur sur des objet de type TEdit, il est de loin préférable, de créer une nouvelle ligne seulement si on en a besoin. Ex : StringGrid1.RowCount := StringGrid1.RowCount + 1; Ou bien StringGrid1.RowCount := NbLignesFichier + 1; A+ ------------------------------- Réponse au message : ------------------------------- Bon, alors allons-y pour plus de détails et merci de s'intéresser à mon problème. Je crée dynamiquement des structures dans un Thread, thread qui est chargé de faire l'acquisition de données sur une ligne série. Une fois les données collectées, je passe le pointeur de cette structure : - à une fonction de ma fenêtre espion, qui l'utilise pour remplir le StringGrid de la manière suivante : MyStringGrid.Cells[0, i] := IntToHex(p^.donnees); où MyStringGrid est le StringGrid où je veux afficher les données que je reçois chaque seconde, i, l'indice de la ligne, compris entre 1 et 10000 (pour mémoire, le stringgrid est initialisé à 10000 lignes) p le pointeru passé en paramètre de la procédure. - à un autre Thread qui se charge de différents affichages puis qui libère l'espace alloué en faisant un: p^.Free(); Dispose(p); Peut-être d'autres infos : J'initialise le StringGrid de la manière suivante: MyStringGrid.RowCount := 10000; La mémoire diminue beaucoup quand j'iconifie : Je pensais que ça aurait donc pu être dû à une sorte de mémoire vidéo alloué par Windows ? J'avoue que je débute en programmation Windows et je ne connaissais pas Delphi auparavant. J'ai repris le code existant, qui utilisait le StringGrid. Il y aurait donc des objets plus adaptés pour ce genre d'application? Je vais déjà éplucher l'aide sur les TBdGrid.... Merci. ------------------------------- Réponse au message : ------------------------------- Ben, personnellement, je ne chercherais pas à afficher 10000 lignes dans un stringgrid ! Les bases de données font faites pour gérer de gros volumes de données et un TDbGrid pour n'en n'afficher qu'une partie : celle qui est visible. Utiliserais-tu des tableaux dynamiques, par hasard ? Donnes un peu plus de détails si tu veux que l'on t'aide. ------------------------------- Réponse au message : ------------------------------- Bonjour, J'ai le problème suivant: Je crée dynamiquement des données puis libère l'espace une fois affichées. Jusque là, pas de soucis, l'espace est alloué puis libéré. Maintenant, je lance une fenêtre espion dans laquelle j'affiche lesdites données dans un StringGrid... et là, ça va plus : l'espace n'est plus libéré ou pas à chaque coup. Résultat, mon application grossit, grossit jusqu'à exploser la mémoire virtuelle. Là où c'est riglo, c'est quand j'iconifie mon application : Le volume mémoire pris par l'application revient à un seuil très bas. Puis si je la re-maximize, elle reprend son niveau initial puis grossit, grossit... Pour être tranquille, j'initialise le nombre de lignes de mon stringGrind à 10000 lignes. Quand j'ouvre la fenêtre, je vois bien l'alocation mémoire associée, mais rien n'y fait: La mémoire grossit alors que je n'ajoute pas de ligne : j'écris dans les 10000 premières lignes... Note : Je travaille sous Delphi 5.0 Bon, ben là j'y comprends rien !!  Merci de m'aider.
|
|
|
|
Re : Fuite mémoire avec StringGrid
le 26/02/2002 16:51:01

Stauf
|
J'ai pas mal galéré avec les new, dispose, free et autres destroy... Moi non plus, je ne trouve pas l'aide bien bien claire... Pour être complet, voici ce que je fait: Dans mon thread d'acquisition: // Création du pointeur sur la structure de données New(PData); // Création de la structure de données PData^ := T_ThreadIO_Data.Create(); // Ensuite je remplis ma structure de données // Puis, je passe le pointeur à ma fenêtre espion (qui s'appelle spy, si, si) G_SpyDlg.AddData(PData); // Et enfin, j'empile le pointeur dans une pile d'échange sécurisée par mutex entre mon thread d'acquisition et mon thread d'affichage Dans la fenêtre espion, j'ai: procedure T_SpyDlg.AddData(p : T_PThreadIO_Data); // T_PThreadIO_Data est le type "pointeur sur la structure de donnees" begin ... MyStringGrid.Cells[0, i] := IntToHex(p^.donnee_D ...); ... end; Et dans mon thread d'affichage, j'ai : // extraction d'un pointeur de la pile sécurisée pData:= Queue.ExtractData(); if (nil <> pData) then begin UpdateDisplay(pData); pData^.Free(); dispose(pData); pdata:=nil; end; Voilà en gros... Et ça, ça plante pas ! Tu préconises P.Free, mais est-ce que àa libère l'espace correspondant à la structure pointée par P ? Quant aux relations avec le client ... Non, mais, il a un besoin assez simple : une bête fenêtre espion... Ca devrait pouvoir se faire, non ? Il veut pouvoir visualiser environ 1/4 d'heure de données reçues. Il y a environ 80 caractères par ligne, une structure de données faisant à peu près une dizaine de lignes... Merci A bientôt j'espère... ------------------------------- Réponse au message : ------------------------------- Ce qui est bizard, c'est qu'il n'y a pas de plantage avec P^.Free; puis Dispose(P); Free est une methode d'objet qui detruit l'objet et libere la mémoire qui lui est associé. Il est précisé dans l'aide de DELPHI, qu'on ne doit pas utiliser Dispose avec Free ou Create. "Dispose" ne doit etre utilisé seulement si on a aloué de la mémoire avec "New". En principe on ne peut utiliser Free seulement avec Nil ( c'est pas obligatoire ) . Nil signifit simplement que le pointeur ne pointe sur rien, mais j'avoue que je n'ai jammais trouvé très claire les explications de l'aide. Ce que je sais pas expérience, c'est que l'on peut faire P.Free; P:=Nil; mais pas l'inverse. Free doit être utilisé avec Create et jammais avec Dispose. Dispose doit être utilisé avec New, FreeMem, GetMem. Le plantage mémoire n'est pas systématique, si on ne perturbe pas l'espace d'autres données ou d'autres objets, mais on peut imaginer les conséquences sur une grosse application. Quand à la libération mémoire d'une stringGrid. En principe, le seul fait de changer le nombre de ligne ( propriété RowCount ) alloue ou libère la mémoire automatiquement, car la propriété appelle une procédure d'allocation de mémoire ( vive la VCL ). Alors 10000 lignes pourquoi pas, mais de combien de données chacunes ? Je ne connais pas le cahier des charges de ton programme, mais le role d'un programmeur est aussi d'expliquer et de convaincre son client qu'il peut y avoir d'autre solutions (j'en sais quelque chose ) pour que cela fonctionne. A condition d'apporter une solution pratique bien sur. A+ ------------------------------- Réponse au message : ------------------------------- Autant pour moi : Je fais en fait : p^.free(); // Je libère la structure pointée par p Dispose (p); p:=nil; Quant au 10000 lignes, c'est une exigence du client. De toutes façons, j'ai besoin de toutes ces lignes ! Au bout de 10000 lignes, je n'ai pas trouvé d'autre moyen que de recopier les 9000 dernières lignes en haut du StringGrid, de manière à avoir dans le StringGrid au moins les 9000 dernières lignes reçues. Y a-t-il un moyen de gérer plus élégamment la mémoire ? En fait, ce qu'il me faut dans cette fenêtre espion, c'est afficher des lignes de données (les 10000 plus récentes reçues... avec une barre de défilement bien sûr) et sans perte de mémoire !!! Autre question : Comment libérer de la mémoire allouée dans un StringGrid par la propriété RowCount ? Si vous avez d'autres idées pour réaliser cela, je suis preneur... Merci ------------------------------- Réponse au message : ------------------------------- Salut. Je ne saisis par tout le problème, mais il y a deux choses qui me choquent : 1 - En général, pour liberer un pointeur, on utilise l'instruction NIL plutot que FREE -> P := Nil; 2 - Résever 10000 ligne d'office pour un StringGrid, est abérant. Une bonne gestion de la mémoire doit se faire de façon dynamique tant que c'est possible. Donc un StringGrid étant une collection de pointeur sur des objet de type TEdit, il est de loin préférable, de créer une nouvelle ligne seulement si on en a besoin. Ex : StringGrid1.RowCount := StringGrid1.RowCount + 1; Ou bien StringGrid1.RowCount := NbLignesFichier + 1; A+ ------------------------------- Réponse au message : ------------------------------- Bon, alors allons-y pour plus de détails et merci de s'intéresser à mon problème. Je crée dynamiquement des structures dans un Thread, thread qui est chargé de faire l'acquisition de données sur une ligne série. Une fois les données collectées, je passe le pointeur de cette structure : - à une fonction de ma fenêtre espion, qui l'utilise pour remplir le StringGrid de la manière suivante : MyStringGrid.Cells[0, i] := IntToHex(p^.donnees); où MyStringGrid est le StringGrid où je veux afficher les données que je reçois chaque seconde, i, l'indice de la ligne, compris entre 1 et 10000 (pour mémoire, le stringgrid est initialisé à 10000 lignes) p le pointeru passé en paramètre de la procédure. - à un autre Thread qui se charge de différents affichages puis qui libère l'espace alloué en faisant un: p^.Free(); Dispose(p); Peut-être d'autres infos : J'initialise le StringGrid de la manière suivante: MyStringGrid.RowCount := 10000; La mémoire diminue beaucoup quand j'iconifie : Je pensais que ça aurait donc pu être dû à une sorte de mémoire vidéo alloué par Windows ? J'avoue que je débute en programmation Windows et je ne connaissais pas Delphi auparavant. J'ai repris le code existant, qui utilisait le StringGrid. Il y aurait donc des objets plus adaptés pour ce genre d'application? Je vais déjà éplucher l'aide sur les TBdGrid.... Merci. ------------------------------- Réponse au message : ------------------------------- Ben, personnellement, je ne chercherais pas à afficher 10000 lignes dans un stringgrid ! Les bases de données font faites pour gérer de gros volumes de données et un TDbGrid pour n'en n'afficher qu'une partie : celle qui est visible. Utiliserais-tu des tableaux dynamiques, par hasard ? Donnes un peu plus de détails si tu veux que l'on t'aide. ------------------------------- Réponse au message : ------------------------------- Bonjour, J'ai le problème suivant: Je crée dynamiquement des données puis libère l'espace une fois affichées. Jusque là, pas de soucis, l'espace est alloué puis libéré. Maintenant, je lance une fenêtre espion dans laquelle j'affiche lesdites données dans un StringGrid... et là, ça va plus : l'espace n'est plus libéré ou pas à chaque coup. Résultat, mon application grossit, grossit jusqu'à exploser la mémoire virtuelle. Là où c'est riglo, c'est quand j'iconifie mon application : Le volume mémoire pris par l'application revient à un seuil très bas. Puis si je la re-maximize, elle reprend son niveau initial puis grossit, grossit... Pour être tranquille, j'initialise le nombre de lignes de mon stringGrind à 10000 lignes. Quand j'ouvre la fenêtre, je vois bien l'alocation mémoire associée, mais rien n'y fait: La mémoire grossit alors que je n'ajoute pas de ligne : j'écris dans les 10000 premières lignes... Note : Je travaille sous Delphi 5.0 Bon, ben là j'y comprends rien !!  Merci de m'aider.
|
|
|
|
Re : Fuite mémoire avec StringGrid
le 27/02/2002 10:59:06

PhGORMAND
|
Dans mon message précédent, j'expliquai que Free doit être utilisé conjointement avec Create, (methode objet), et Dispose seulement avec New. Sur ce point, l'aide de DELPHI est très claire. Je n'ai pas encore le temps d'examiner le code, mais si c'est pour garder une trace des donnéees reçues, il me parrait plus judicieux et plus simple d'utiliser un listbox, ou une StringList pour cumuler les données : ListBox1.Items.Add(ChaineDeDonnees); If ListBox1.Items.Count > 10000 Then ListBox1.Items.Delete(0); Si on veut voir le numero de donnée de chaque ligne, on peut ajouter ce numéro : ChaineDeDonnees := IntToStr(Ligne) + ' - ' + ChaineDeDonnees; Au fait, pData c'est quel type de structure ? A+ ------------------------------- Réponse au message : ------------------------------- J'ai pas mal galéré avec les new, dispose, free et autres destroy... Moi non plus, je ne trouve pas l'aide bien bien claire... Pour être complet, voici ce que je fait: Dans mon thread d'acquisition: // Création du pointeur sur la structure de données New(PData); // Création de la structure de données PData^ := T_ThreadIO_Data.Create(); // Ensuite je remplis ma structure de données // Puis, je passe le pointeur à ma fenêtre espion (qui s'appelle spy, si, si) G_SpyDlg.AddData(PData); // Et enfin, j'empile le pointeur dans une pile d'échange sécurisée par mutex entre mon thread d'acquisition et mon thread d'affichage Dans la fenêtre espion, j'ai: procedure T_SpyDlg.AddData(p : T_PThreadIO_Data); // T_PThreadIO_Data est le type "pointeur sur la structure de donnees" begin ... MyStringGrid.Cells[0, i] := IntToHex(p^.donnee_D ...); ... end; Et dans mon thread d'affichage, j'ai : // extraction d'un pointeur de la pile sécurisée pData:= Queue.ExtractData(); if (nil <> pData) then begin UpdateDisplay(pData); pData^.Free(); dispose(pData); pdata:=nil; end; Voilà en gros... Et ça, ça plante pas ! Tu préconises P.Free, mais est-ce que àa libère l'espace correspondant à la structure pointée par P ? Quant aux relations avec le client ... Non, mais, il a un besoin assez simple : une bête fenêtre espion... Ca devrait pouvoir se faire, non ? Il veut pouvoir visualiser environ 1/4 d'heure de données reçues. Il y a environ 80 caractères par ligne, une structure de données faisant à peu près une dizaine de lignes... Merci A bientôt j'espère... ------------------------------- Réponse au message : ------------------------------- Ce qui est bizard, c'est qu'il n'y a pas de plantage avec P^.Free; puis Dispose(P); Free est une methode d'objet qui detruit l'objet et libere la mémoire qui lui est associé. Il est précisé dans l'aide de DELPHI, qu'on ne doit pas utiliser Dispose avec Free ou Create. "Dispose" ne doit etre utilisé seulement si on a aloué de la mémoire avec "New". En principe on ne peut utiliser Free seulement avec Nil ( c'est pas obligatoire ) . Nil signifit simplement que le pointeur ne pointe sur rien, mais j'avoue que je n'ai jammais trouvé très claire les explications de l'aide. Ce que je sais pas expérience, c'est que l'on peut faire P.Free; P:=Nil; mais pas l'inverse. Free doit être utilisé avec Create et jammais avec Dispose. Dispose doit être utilisé avec New, FreeMem, GetMem. Le plantage mémoire n'est pas systématique, si on ne perturbe pas l'espace d'autres données ou d'autres objets, mais on peut imaginer les conséquences sur une grosse application. Quand à la libération mémoire d'une stringGrid. En principe, le seul fait de changer le nombre de ligne ( propriété RowCount ) alloue ou libère la mémoire automatiquement, car la propriété appelle une procédure d'allocation de mémoire ( vive la VCL ). Alors 10000 lignes pourquoi pas, mais de combien de données chacunes ? Je ne connais pas le cahier des charges de ton programme, mais le role d'un programmeur est aussi d'expliquer et de convaincre son client qu'il peut y avoir d'autre solutions (j'en sais quelque chose ) pour que cela fonctionne. A condition d'apporter une solution pratique bien sur. A+ ------------------------------- Réponse au message : ------------------------------- Autant pour moi : Je fais en fait : p^.free(); // Je libère la structure pointée par p Dispose (p); p:=nil; Quant au 10000 lignes, c'est une exigence du client. De toutes façons, j'ai besoin de toutes ces lignes ! Au bout de 10000 lignes, je n'ai pas trouvé d'autre moyen que de recopier les 9000 dernières lignes en haut du StringGrid, de manière à avoir dans le StringGrid au moins les 9000 dernières lignes reçues. Y a-t-il un moyen de gérer plus élégamment la mémoire ? En fait, ce qu'il me faut dans cette fenêtre espion, c'est afficher des lignes de données (les 10000 plus récentes reçues... avec une barre de défilement bien sûr) et sans perte de mémoire !!! Autre question : Comment libérer de la mémoire allouée dans un StringGrid par la propriété RowCount ? Si vous avez d'autres idées pour réaliser cela, je suis preneur... Merci ------------------------------- Réponse au message : ------------------------------- Salut. Je ne saisis par tout le problème, mais il y a deux choses qui me choquent : 1 - En général, pour liberer un pointeur, on utilise l'instruction NIL plutot que FREE -> P := Nil; 2 - Résever 10000 ligne d'office pour un StringGrid, est abérant. Une bonne gestion de la mémoire doit se faire de façon dynamique tant que c'est possible. Donc un StringGrid étant une collection de pointeur sur des objet de type TEdit, il est de loin préférable, de créer une nouvelle ligne seulement si on en a besoin. Ex : StringGrid1.RowCount := StringGrid1.RowCount + 1; Ou bien StringGrid1.RowCount := NbLignesFichier + 1; A+ ------------------------------- Réponse au message : ------------------------------- Bon, alors allons-y pour plus de détails et merci de s'intéresser à mon problème. Je crée dynamiquement des structures dans un Thread, thread qui est chargé de faire l'acquisition de données sur une ligne série. Une fois les données collectées, je passe le pointeur de cette structure : - à une fonction de ma fenêtre espion, qui l'utilise pour remplir le StringGrid de la manière suivante : MyStringGrid.Cells[0, i] := IntToHex(p^.donnees); où MyStringGrid est le StringGrid où je veux afficher les données que je reçois chaque seconde, i, l'indice de la ligne, compris entre 1 et 10000 (pour mémoire, le stringgrid est initialisé à 10000 lignes) p le pointeru passé en paramètre de la procédure. - à un autre Thread qui se charge de différents affichages puis qui libère l'espace alloué en faisant un: p^.Free(); Dispose(p); Peut-être d'autres infos : J'initialise le StringGrid de la manière suivante: MyStringGrid.RowCount := 10000; La mémoire diminue beaucoup quand j'iconifie : Je pensais que ça aurait donc pu être dû à une sorte de mémoire vidéo alloué par Windows ? J'avoue que je débute en programmation Windows et je ne connaissais pas Delphi auparavant. J'ai repris le code existant, qui utilisait le StringGrid. Il y aurait donc des objets plus adaptés pour ce genre d'application? Je vais déjà éplucher l'aide sur les TBdGrid.... Merci. ------------------------------- Réponse au message : ------------------------------- Ben, personnellement, je ne chercherais pas à afficher 10000 lignes dans un stringgrid ! Les bases de données font faites pour gérer de gros volumes de données et un TDbGrid pour n'en n'afficher qu'une partie : celle qui est visible. Utiliserais-tu des tableaux dynamiques, par hasard ? Donnes un peu plus de détails si tu veux que l'on t'aide. ------------------------------- Réponse au message : ------------------------------- Bonjour, J'ai le problème suivant: Je crée dynamiquement des données puis libère l'espace une fois affichées. Jusque là, pas de soucis, l'espace est alloué puis libéré. Maintenant, je lance une fenêtre espion dans laquelle j'affiche lesdites données dans un StringGrid... et là, ça va plus : l'espace n'est plus libéré ou pas à chaque coup. Résultat, mon application grossit, grossit jusqu'à exploser la mémoire virtuelle. Là où c'est riglo, c'est quand j'iconifie mon application : Le volume mémoire pris par l'application revient à un seuil très bas. Puis si je la re-maximize, elle reprend son niveau initial puis grossit, grossit... Pour être tranquille, j'initialise le nombre de lignes de mon stringGrind à 10000 lignes. Quand j'ouvre la fenêtre, je vois bien l'alocation mémoire associée, mais rien n'y fait: La mémoire grossit alors que je n'ajoute pas de ligne : j'écris dans les 10000 premières lignes... Note : Je travaille sous Delphi 5.0 Bon, ben là j'y comprends rien !!  Merci de m'aider.
|
|
|
|
Re : Fuite mémoire avec StringGrid
le 27/02/2002 11:17:21

Stauf
|
La solution de la TListBox me semble intéressante (surtout pour supprimer les premières lignes). Le seul petit problème est que j'ai plusieurs colonnes de données, mais je peux le contourner en mettant autant de TListBox que de colonnes. Pour répondre à la question: PData est du type T_PThreadIO_Data, c'est-à-dire pointeur sur le type T_ThreadIO_Data, qui est une structure de données. Merci bien, je vais tester tout de suite la TListBox... A+ ------------------------------- Réponse au message : ------------------------------- Dans mon message précédent, j'expliquai que Free doit être utilisé conjointement avec Create, (methode objet), et Dispose seulement avec New. Sur ce point, l'aide de DELPHI est très claire. Je n'ai pas encore le temps d'examiner le code, mais si c'est pour garder une trace des donnéees reçues, il me parrait plus judicieux et plus simple d'utiliser un listbox, ou une StringList pour cumuler les données : ListBox1.Items.Add(ChaineDeDonnees); If ListBox1.Items.Count > 10000 Then ListBox1.Items.Delete(0); Si on veut voir le numero de donnée de chaque ligne, on peut ajouter ce numéro : ChaineDeDonnees := IntToStr(Ligne) + ' - ' + ChaineDeDonnees; Au fait, pData c'est quel type de structure ? A+ ------------------------------- Réponse au message : ------------------------------- J'ai pas mal galéré avec les new, dispose, free et autres destroy... Moi non plus, je ne trouve pas l'aide bien bien claire... Pour être complet, voici ce que je fait: Dans mon thread d'acquisition: // Création du pointeur sur la structure de données New(PData); // Création de la structure de données PData^ := T_ThreadIO_Data.Create(); // Ensuite je remplis ma structure de données // Puis, je passe le pointeur à ma fenêtre espion (qui s'appelle spy, si, si) G_SpyDlg.AddData(PData); // Et enfin, j'empile le pointeur dans une pile d'échange sécurisée par mutex entre mon thread d'acquisition et mon thread d'affichage Dans la fenêtre espion, j'ai: procedure T_SpyDlg.AddData(p : T_PThreadIO_Data); // T_PThreadIO_Data est le type "pointeur sur la structure de donnees" begin ... MyStringGrid.Cells[0, i] := IntToHex(p^.donnee_D ...); ... end; Et dans mon thread d'affichage, j'ai : // extraction d'un pointeur de la pile sécurisée pData:= Queue.ExtractData(); if (nil <> pData) then begin UpdateDisplay(pData); pData^.Free(); dispose(pData); pdata:=nil; end; Voilà en gros... Et ça, ça plante pas ! Tu préconises P.Free, mais est-ce que àa libère l'espace correspondant à la structure pointée par P ? Quant aux relations avec le client ... Non, mais, il a un besoin assez simple : une bête fenêtre espion... Ca devrait pouvoir se faire, non ? Il veut pouvoir visualiser environ 1/4 d'heure de données reçues. Il y a environ 80 caractères par ligne, une structure de données faisant à peu près une dizaine de lignes... Merci A bientôt j'espère... ------------------------------- Réponse au message : ------------------------------- Ce qui est bizard, c'est qu'il n'y a pas de plantage avec P^.Free; puis Dispose(P); Free est une methode d'objet qui detruit l'objet et libere la mémoire qui lui est associé. Il est précisé dans l'aide de DELPHI, qu'on ne doit pas utiliser Dispose avec Free ou Create. "Dispose" ne doit etre utilisé seulement si on a aloué de la mémoire avec "New". En principe on ne peut utiliser Free seulement avec Nil ( c'est pas obligatoire ) . Nil signifit simplement que le pointeur ne pointe sur rien, mais j'avoue que je n'ai jammais trouvé très claire les explications de l'aide. Ce que je sais pas expérience, c'est que l'on peut faire P.Free; P:=Nil; mais pas l'inverse. Free doit être utilisé avec Create et jammais avec Dispose. Dispose doit être utilisé avec New, FreeMem, GetMem. Le plantage mémoire n'est pas systématique, si on ne perturbe pas l'espace d'autres données ou d'autres objets, mais on peut imaginer les conséquences sur une grosse application. Quand à la libération mémoire d'une stringGrid. En principe, le seul fait de changer le nombre de ligne ( propriété RowCount ) alloue ou libère la mémoire automatiquement, car la propriété appelle une procédure d'allocation de mémoire ( vive la VCL ). Alors 10000 lignes pourquoi pas, mais de combien de données chacunes ? Je ne connais pas le cahier des charges de ton programme, mais le role d'un programmeur est aussi d'expliquer et de convaincre son client qu'il peut y avoir d'autre solutions (j'en sais quelque chose ) pour que cela fonctionne. A condition d'apporter une solution pratique bien sur. A+ ------------------------------- Réponse au message : ------------------------------- Autant pour moi : Je fais en fait : p^.free(); // Je libère la structure pointée par p Dispose (p); p:=nil; Quant au 10000 lignes, c'est une exigence du client. De toutes façons, j'ai besoin de toutes ces lignes ! Au bout de 10000 lignes, je n'ai pas trouvé d'autre moyen que de recopier les 9000 dernières lignes en haut du StringGrid, de manière à avoir dans le StringGrid au moins les 9000 dernières lignes reçues. Y a-t-il un moyen de gérer plus élégamment la mémoire ? En fait, ce qu'il me faut dans cette fenêtre espion, c'est afficher des lignes de données (les 10000 plus récentes reçues... avec une barre de défilement bien sûr) et sans perte de mémoire !!! Autre question : Comment libérer de la mémoire allouée dans un StringGrid par la propriété RowCount ? Si vous avez d'autres idées pour réaliser cela, je suis preneur... Merci ------------------------------- Réponse au message : ------------------------------- Salut. Je ne saisis par tout le problème, mais il y a deux choses qui me choquent : 1 - En général, pour liberer un pointeur, on utilise l'instruction NIL plutot que FREE -> P := Nil; 2 - Résever 10000 ligne d'office pour un StringGrid, est abérant. Une bonne gestion de la mémoire doit se faire de façon dynamique tant que c'est possible. Donc un StringGrid étant une collection de pointeur sur des objet de type TEdit, il est de loin préférable, de créer une nouvelle ligne seulement si on en a besoin. Ex : StringGrid1.RowCount := StringGrid1.RowCount + 1; Ou bien StringGrid1.RowCount := NbLignesFichier + 1; A+ ------------------------------- Réponse au message : ------------------------------- Bon, alors allons-y pour plus de détails et merci de s'intéresser à mon problème. Je crée dynamiquement des structures dans un Thread, thread qui est chargé de faire l'acquisition de données sur une ligne série. Une fois les données collectées, je passe le pointeur de cette structure : - à une fonction de ma fenêtre espion, qui l'utilise pour remplir le StringGrid de la manière suivante : MyStringGrid.Cells[0, i] := IntToHex(p^.donnees); où MyStringGrid est le StringGrid où je veux afficher les données que je reçois chaque seconde, i, l'indice de la ligne, compris entre 1 et 10000 (pour mémoire, le stringgrid est initialisé à 10000 lignes) p le pointeru passé en paramètre de la procédure. - à un autre Thread qui se charge de différents affichages puis qui libère l'espace alloué en faisant un: p^.Free(); Dispose(p); Peut-être d'autres infos : J'initialise le StringGrid de la manière suivante: MyStringGrid.RowCount := 10000; La mémoire diminue beaucoup quand j'iconifie : Je pensais que ça aurait donc pu être dû à une sorte de mémoire vidéo alloué par Windows ? J'avoue que je débute en programmation Windows et je ne connaissais pas Delphi auparavant. J'ai repris le code existant, qui utilisait le StringGrid. Il y aurait donc des objets plus adaptés pour ce genre d'application? Je vais déjà éplucher l'aide sur les TBdGrid.... Merci. ------------------------------- Réponse au message : ------------------------------- Ben, personnellement, je ne chercherais pas à afficher 10000 lignes dans un stringgrid ! Les bases de données font faites pour gérer de gros volumes de données et un TDbGrid pour n'en n'afficher qu'une partie : celle qui est visible. Utiliserais-tu des tableaux dynamiques, par hasard ? Donnes un peu plus de détails si tu veux que l'on t'aide. ------------------------------- Réponse au message : ------------------------------- Bonjour, J'ai le problème suivant: Je crée dynamiquement des données puis libère l'espace une fois affichées. Jusque là, pas de soucis, l'espace est alloué puis libéré. Maintenant, je lance une fenêtre espion dans laquelle j'affiche lesdites données dans un StringGrid... et là, ça va plus : l'espace n'est plus libéré ou pas à chaque coup. Résultat, mon application grossit, grossit jusqu'à exploser la mémoire virtuelle. Là où c'est riglo, c'est quand j'iconifie mon application : Le volume mémoire pris par l'application revient à un seuil très bas. Puis si je la re-maximize, elle reprend son niveau initial puis grossit, grossit... Pour être tranquille, j'initialise le nombre de lignes de mon stringGrind à 10000 lignes. Quand j'ouvre la fenêtre, je vois bien l'alocation mémoire associée, mais rien n'y fait: La mémoire grossit alors que je n'ajoute pas de ligne : j'écris dans les 10000 premières lignes... Note : Je travaille sous Delphi 5.0 Bon, ben là j'y comprends rien !!  Merci de m'aider.
|
|
|
|
Re : Fuite mémoire avec StringGrid
le 28/02/2002 09:25:54

PhGORMAND
|
Bon ! Je crois que je n'ai pas tout compris. 1 - Ta structure pData, c'est quoi exactement ? 2 - As tu vraiment besoin de déclarer P comme pointeur ? 3 - Est ce que tu ne mélanges pas les pointeurs et les classes, New et Create ? 4 - Alors si tu dois afficher des données differentes, effectivement la StringGrid peut être préférable. 5 - Si tu donnes les infos au compte goute, c'est plus difficile de répondre. Je veux bien me pencher sur ton problème à tête reposée, il m'intéresse. Alors envois moi ton source complet. EMail : philippe.gormand@free.fr URL : http://philippe.gormand.free.fr/ ------------------------------- Réponse au message : ------------------------------- La solution de la TListBox me semble intéressante (surtout pour supprimer les premières lignes). Le seul petit problème est que j'ai plusieurs colonnes de données, mais je peux le contourner en mettant autant de TListBox que de colonnes. Pour répondre à la question: PData est du type T_PThreadIO_Data, c'est-à-dire pointeur sur le type T_ThreadIO_Data, qui est une structure de données. Merci bien, je vais tester tout de suite la TListBox... A+ ------------------------------- Réponse au message : ------------------------------- Dans mon message précédent, j'expliquai que Free doit être utilisé conjointement avec Create, (methode objet), et Dispose seulement avec New. Sur ce point, l'aide de DELPHI est très claire. Je n'ai pas encore le temps d'examiner le code, mais si c'est pour garder une trace des donnéees reçues, il me parrait plus judicieux et plus simple d'utiliser un listbox, ou une StringList pour cumuler les données : ListBox1.Items.Add(ChaineDeDonnees); If ListBox1.Items.Count > 10000 Then ListBox1.Items.Delete(0); Si on veut voir le numero de donnée de chaque ligne, on peut ajouter ce numéro : ChaineDeDonnees := IntToStr(Ligne) + ' - ' + ChaineDeDonnees; Au fait, pData c'est quel type de structure ? A+ ------------------------------- Réponse au message : ------------------------------- J'ai pas mal galéré avec les new, dispose, free et autres destroy... Moi non plus, je ne trouve pas l'aide bien bien claire... Pour être complet, voici ce que je fait: Dans mon thread d'acquisition: // Création du pointeur sur la structure de données New(PData); // Création de la structure de données PData^ := T_ThreadIO_Data.Create(); // Ensuite je remplis ma structure de données // Puis, je passe le pointeur à ma fenêtre espion (qui s'appelle spy, si, si) G_SpyDlg.AddData(PData); // Et enfin, j'empile le pointeur dans une pile d'échange sécurisée par mutex entre mon thread d'acquisition et mon thread d'affichage Dans la fenêtre espion, j'ai: procedure T_SpyDlg.AddData(p : T_PThreadIO_Data); // T_PThreadIO_Data est le type "pointeur sur la structure de donnees" begin ... MyStringGrid.Cells[0, i] := IntToHex(p^.donnee_D ...); ... end; Et dans mon thread d'affichage, j'ai : // extraction d'un pointeur de la pile sécurisée pData:= Queue.ExtractData(); if (nil <> pData) then begin UpdateDisplay(pData); pData^.Free(); dispose(pData); pdata:=nil; end; Voilà en gros... Et ça, ça plante pas ! Tu préconises P.Free, mais est-ce que àa libère l'espace correspondant à la structure pointée par P ? Quant aux relations avec le client ... Non, mais, il a un besoin assez simple : une bête fenêtre espion... Ca devrait pouvoir se faire, non ? Il veut pouvoir visualiser environ 1/4 d'heure de données reçues. Il y a environ 80 caractères par ligne, une structure de données faisant à peu près une dizaine de lignes... Merci A bientôt j'espère... ------------------------------- Réponse au message : ------------------------------- Ce qui est bizard, c'est qu'il n'y a pas de plantage avec P^.Free; puis Dispose(P); Free est une methode d'objet qui detruit l'objet et libere la mémoire qui lui est associé. Il est précisé dans l'aide de DELPHI, qu'on ne doit pas utiliser Dispose avec Free ou Create. "Dispose" ne doit etre utilisé seulement si on a aloué de la mémoire avec "New". En principe on ne peut utiliser Free seulement avec Nil ( c'est pas obligatoire ) . Nil signifit simplement que le pointeur ne pointe sur rien, mais j'avoue que je n'ai jammais trouvé très claire les explications de l'aide. Ce que je sais pas expérience, c'est que l'on peut faire P.Free; P:=Nil; mais pas l'inverse. Free doit être utilisé avec Create et jammais avec Dispose. Dispose doit être utilisé avec New, FreeMem, GetMem. Le plantage mémoire n'est pas systématique, si on ne perturbe pas l'espace d'autres données ou d'autres objets, mais on peut imaginer les conséquences sur une grosse application. Quand à la libération mémoire d'une stringGrid. En principe, le seul fait de changer le nombre de ligne ( propriété RowCount ) alloue ou libère la mémoire automatiquement, car la propriété appelle une procédure d'allocation de mémoire ( vive la VCL ). Alors 10000 lignes pourquoi pas, mais de combien de données chacunes ? Je ne connais pas le cahier des charges de ton programme, mais le role d'un programmeur est aussi d'expliquer et de convaincre son client qu'il peut y avoir d'autre solutions (j'en sais quelque chose ) pour que cela fonctionne. A condition d'apporter une solution pratique bien sur. A+ ------------------------------- Réponse au message : ------------------------------- Autant pour moi : Je fais en fait : p^.free(); // Je libère la structure pointée par p Dispose (p); p:=nil; Quant au 10000 lignes, c'est une exigence du client. De toutes façons, j'ai besoin de toutes ces lignes ! Au bout de 10000 lignes, je n'ai pas trouvé d'autre moyen que de recopier les 9000 dernières lignes en haut du StringGrid, de manière à avoir dans le StringGrid au moins les 9000 dernières lignes reçues. Y a-t-il un moyen de gérer plus élégamment la mémoire ? En fait, ce qu'il me faut dans cette fenêtre espion, c'est afficher des lignes de données (les 10000 plus récentes reçues... avec une barre de défilement bien sûr) et sans perte de mémoire !!! Autre question : Comment libérer de la mémoire allouée dans un StringGrid par la propriété RowCount ? Si vous avez d'autres idées pour réaliser cela, je suis preneur... Merci ------------------------------- Réponse au message : ------------------------------- Salut. Je ne saisis par tout le problème, mais il y a deux choses qui me choquent : 1 - En général, pour liberer un pointeur, on utilise l'instruction NIL plutot que FREE -> P := Nil; 2 - Résever 10000 ligne d'office pour un StringGrid, est abérant. Une bonne gestion de la mémoire doit se faire de façon dynamique tant que c'est possible. Donc un StringGrid étant une collection de pointeur sur des objet de type TEdit, il est de loin préférable, de créer une nouvelle ligne seulement si on en a besoin. Ex : StringGrid1.RowCount := StringGrid1.RowCount + 1; Ou bien StringGrid1.RowCount := NbLignesFichier + 1; A+ ------------------------------- Réponse au message : ------------------------------- Bon, alors allons-y pour plus de détails et merci de s'intéresser à mon problème. Je crée dynamiquement des structures dans un Thread, thread qui est chargé de faire l'acquisition de données sur une ligne série. Une fois les données collectées, je passe le pointeur de cette structure : - à une fonction de ma fenêtre espion, qui l'utilise pour remplir le StringGrid de la manière suivante : MyStringGrid.Cells[0, i] := IntToHex(p^.donnees); où MyStringGrid est le StringGrid où je veux afficher les données que je reçois chaque seconde, i, l'indice de la ligne, compris entre 1 et 10000 (pour mémoire, le stringgrid est initialisé à 10000 lignes) p le pointeru passé en paramètre de la procédure. - à un autre Thread qui se charge de différents affichages puis qui libère l'espace alloué en faisant un: p^.Free(); Dispose(p); Peut-être d'autres infos : J'initialise le StringGrid de la manière suivante: MyStringGrid.RowCount := 10000; La mémoire diminue beaucoup quand j'iconifie : Je pensais que ça aurait donc pu être dû à une sorte de mémoire vidéo alloué par Windows ? J'avoue que je débute en programmation Windows et je ne connaissais pas Delphi auparavant. J'ai repris le code existant, qui utilisait le StringGrid. Il y aurait donc des objets plus adaptés pour ce genre d'application? Je vais déjà éplucher l'aide sur les TBdGrid.... Merci. ------------------------------- Réponse au message : ------------------------------- Ben, personnellement, je ne chercherais pas à afficher 10000 lignes dans un stringgrid ! Les bases de données font faites pour gérer de gros volumes de données et un TDbGrid pour n'en n'afficher qu'une partie : celle qui est visible. Utiliserais-tu des tableaux dynamiques, par hasard ? Donnes un peu plus de détails si tu veux que l'on t'aide. ------------------------------- Réponse au message : ------------------------------- Bonjour, J'ai le problème suivant: Je crée dynamiquement des données puis libère l'espace une fois affichées. Jusque là, pas de soucis, l'espace est alloué puis libéré. Maintenant, je lance une fenêtre espion dans laquelle j'affiche lesdites données dans un StringGrid... et là, ça va plus : l'espace n'est plus libéré ou pas à chaque coup. Résultat, mon application grossit, grossit jusqu'à exploser la mémoire virtuelle. Là où c'est riglo, c'est quand j'iconifie mon application : Le volume mémoire pris par l'application revient à un seuil très bas. Puis si je la re-maximize, elle reprend son niveau initial puis grossit, grossit... Pour être tranquille, j'initialise le nombre de lignes de mon stringGrind à 10000 lignes. Quand j'ouvre la fenêtre, je vois bien l'alocation mémoire associée, mais rien n'y fait: La mémoire grossit alors que je n'ajoute pas de ligne : j'écris dans les 10000 premières lignes... Note : Je travaille sous Delphi 5.0 Bon, ben là j'y comprends rien !!  Merci de m'aider.
|
|
|
Classé sous : application, espace, stringgrid, mémoire, grossit
|
CalendriCode
| | | L | M | M | J | V | S | D |
| | 1 | 2 | 3 | 4 | 5 | 6 |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 | 31 | | | |
|
Téléchargements
Logiciels à télécharger sur le même thème :
|
|