IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++Builder Discussion :

Mes 5 lignes de code bouffent de la mémoire


Sujet :

C++Builder

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre émérite
    Avatar de Interruption13h
    Inscrit en
    Août 2005
    Messages
    603
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 603
    Par défaut Mes 5 lignes de code bouffent de la mémoire
    Salut,


    Voila, je suis entrain de developper un petit logiciel de gestion de stock, normalment tout se déroule très bien, sauf voila, je remarque que ce logiciel bouf de plus en plus de mémoire, et ça pendant l'execution, Et ça malgrès que je suis très strict avec les new et delete.
    J'ai utilisé CodeGuard, apparament tout marche bien comme je l'ai dis .

    Voila, après certain éliminations, je croi que j'ai tronqué un morceau du code qui boufe et augmente l'occupation de la mémoire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
     
    void __fastcall QueryExecute(TQuery *Query,AnsiString Requete)
    {
    Query->Close();
    Query->SQL->Clear();
    Query->SQL->Add(Requete);
    Query->ExecSQL();
    Query->Active=true;
    }
    Vois l'aurez compri, c'est une fonction qui me permet d'executer certains type de requêtes SQL, et d'en tirer les resultats !

    Pour enlever le doute, j'ai créer un nouveau projet qui utilise presque exclusivement cette fonction, autrement dit : une fiche, un Query1 et un Bouton qui fait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    QueryExecute(Query1,"Select* FROM BDDs\\Produits.db");
    A chaque fois que je clique sur le bouton je remarque l'augmentation de la mémoire, à peut prêt 80 à 120 Ko, malgrès qu'il affiche le même resultat(puisque la même requête), et à chaque fois je ferme le Query1 (je pense que ça devrai libérer la mémoire allouée pour contenir les information des enregistrement! !?).
    Le pire, quand j'ai placé un Timer qui fait le même travail que le bouton à un interval de 500ms, lol, il arrive jusqu'à ~32Mo alors qu'au début ne faisait à peinne 8Mo , et la j'aurai une belle violation "Insufisant memory for this operation...". Donc la, ça devient serieux, je veux pas que l'utilisateur final de mon logiciel aura une violation qui fait planter le tout


    Malgrès que j'ai modifié le code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    void __fastcall QueryExecute(TQuery *Query,AnsiString Requete)
    {
    try
              {
              Query->Close();
              Query->SQL->Clear();
              Query->SQL->Add(Requete);
              Query->ExecSQL();
              Query->Active=true;
              }
    catch(...)
              {
              ShowMessage("Nous vous en fait pas, c'est juste une petite erreur, ça va marcher :)");
              }
    }
    Dès le premier catch, on peu plus ré-executer la requête, çàd que j'aurai toujours mon message du catch !


    Mes questions si vous le permettez :
    1- Esque c'est normal cette augmentation ?
    2- Si oui, es qu'il y a pas une solution pour la libérer cette mémoire explicitement ?
    3- Y aurai pas une autre solution pour accéder à mes enregistrement à partir d'une requête (On sait jamais...) ?
    4- Si y a pas d'autre(s) solution(s), esqu'il y a pas moyen d'augmenter un peu la taille de mémoire que peut utiliser mon soft ?

    Informations sur ma machine :

    OS : WinXP Professionnel SP2
    IDE : BCB6
    RAM : SDRAM 256Mo
    CPU : 1.7GHz
    Progarmmeur :



    Merci d'avance pour votre aide


    A+

  2. #2
    Membre chevronné
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    349
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 349
    Par défaut
    Une requête comme:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    "Select* FROM BDDs\\Produits.db"
    sélectionne tous les champs de tous les enregistrements de ta table. Si ta table est importante, c'est tout à fait normal que cela consomme beaucoup de mémoire.

    Vois déjà si tu peux optimiser tes requêtes.

    Au niveau de ton Query, tu as aussi des paramètres qui influencent l'occupation mémoire (comme CachedUpdates). De même au niveau de ton Database (dépend de ta base de données).

  3. #3
    Membre éprouvé
    Avatar de Sunchaser
    Homme Profil pro
    OPNI (Objet Programmant Non Identifié)
    Inscrit en
    Décembre 2004
    Messages
    2 059
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : OPNI (Objet Programmant Non Identifié)
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Décembre 2004
    Messages : 2 059
    Par défaut
    Bonjour,

    Juste une petite remarque au passage : si c'est une requête afin de présenter des données (de type SELECT, et donc sans INSERT et autres ...), je crois qu'un simple suffit.
    De même, je ne suis pas sur que la succession de 'ExecSQL()' et de 'Active=true' soit nécéssaire ... juste une supposition la ...
    Bon courage,
    @ +

  4. #4
    Rédacteur
    Avatar de blondelle
    Homme Profil pro
    Inscrit en
    Mars 2006
    Messages
    2 738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 738
    Par défaut
    Salut Interruption13h:
    J'ai recupere des exemple dans les tuto Delphi et j'ai ceci:
    ADOQuery1->Close();
    ADOQuery1->SQL->Clear();
    ADOQuery1->SQL->Add("INSERT INTO " "C:\\Documents and Settings\\blondelle\\Mes documents\\PROG_POUR_FAQ\\BASE_DONNEES\\LectureBloc.mdb,Employés"); // SELECT * FROM maBdd1.mdb.Essai");
    ADOQuery1->SQL->Add("SELECT *");
    ADOQuery1->SQL->Add("FROM " "C:\\Documents and Settings\\blondelle\\Mes documents\\PROG_POUR_FAQ\\BASE_DONNEES\\maBdd1.mdb,Essai");
    ADOQuery1->ExecSQL();

    ADOQuery1->Open(); <------
    Normalement tu ferme le Query tu devrait le reouvrir, le fait d'ecrire ADOQuery1->Active=true; pourrait peut etre ouvrir une connection qui s'ajoute a la precedente et ta requete augmenterais d'une maniere exponentielle

  5. #5
    Membre émérite
    Avatar de Interruption13h
    Inscrit en
    Août 2005
    Messages
    603
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 603
    Par défaut
    Citation Envoyé par Sunchaser
    je crois qu'un simple suffit.
    De même, je ne suis pas sur que la succession de 'ExecSQL()' et de 'Active=true' soit nécéssaire ... juste une supposition la ...



    Holala, je savais même pas qu'il y avait une différence entre Active=true et Open() ...
    J'ai modifié le truc, et la mémoire allouée reste collée à ~9200Ko

    Voici le code comme vous me l'avais indiqué :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
     
    Query->Close();
    Query->SQL->Clear();
    Query->SQL->Add(MaRequete);
    Query->Open();
    Merci les gars, ça fonctionne héhé, très bien cool mec


    Edit :
    On parle aussi de la méthode Prepare de TQuery :


    [code]
    Sends a query to the Borland Database Engine (BDE) and the server for optimization prior to execution.

    void __fastcall Prepare(void);

    Description

    Call Prepare to have the BDE and a remote database server allocate resources for the query and to perform additional optimizations. Calling Prepare before executing a query improves application performance.

    C++Builder automatically prepares a query if it is executed without first being prepared. After execution, C++Builder unprepares the query. When a query will be executed a number of times, an application should always explicitly prepare the query to avoid multiple and unnecessary prepares and unprepares.

    Preparing a query consumes some database resources, so it is good practice for an application to unprepare a query once it is done using it. The UnPrepare method unprepares a query.
    [/code]


    A la prochaîne !!


  6. #6
    Membre éclairé
    Homme Profil pro
    Consultant technique
    Inscrit en
    Juillet 2002
    Messages
    519
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Consultant technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2002
    Messages : 519
    Par défaut
    Vous devriez mettre cette solution dans la FAQ de C++Builder.

    Je viens de m'apercevoir qu'un de mes programmes plantait après un long moment pour la même raison.

  7. #7
    Membre émérite
    Avatar de Interruption13h
    Inscrit en
    Août 2005
    Messages
    603
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 603
    Par défaut
    Citation Envoyé par josse95
    Une requête comme:

    [code]
    sélectionne tous les champs de tous les enregistrements de ta table. Si ta table est importante, c'est tout à fait normal que cela consomme beaucoup de mémoire.

    Vois déjà si tu peux optimiser tes requêtes.
    Salut !

    Merci pour ta réponse josse95.
    C'est sûr que dans mon logiciel j'ai pas créé cette fonction pour afficher toute une table à la fois , c'est juste un test, et pour détecter plus rapidement l'erreur, j'ai exécuté une requête qui me prendra le maximum de mémoire !
    Mais c sûre aussi qu'il faut prendre en charge ce type d'erreurs, et y aura sûrement des requête qui vont afficher plus de 200 enregistrements (de taille différents selon les champs affichés...), je prend l'exemple des historiques, du bilan, statistiques...etc.

    Par exemple, j'ai implémenter cette fonction, dans une classe appelée Produit, et lors de l'instanciation d'un objet Produit, il a comme paramètre l'identifiant du produit ainsi avec une requête du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    SELECT * FROM BDDs\\Produits.db WHERE Id_Produit=x
    J'aurai toute les informations du produit.



    Citation Envoyé par josse95
    Au niveau de ton Query, tu as aussi des paramètres qui influencent l'occupation mémoire (comme CachedUpdates). De même au niveau de ton Database.
    J'ai pas utiliser le cache, j'ai testé avec une application basique, très simple, ne faisant que appeler cette fonction de façon répétitif, et sans changer ces propriétés de Query.





    D'après ce que je pense, même si la table est très grande, normalement y a un moyen de libérer la mémoire prise par un TQuery pour afficher les sélection des enregistrement des tables, et non pas la mémoire alloué pour instancier ce l'objet Query1 lui même si je me suis bien exprimé !




    Voila, merci encore pour ta reponse !



    Excusez pour mon français aussi






    A+

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [XL-2010] Ligne de code posant problème dans tous mes programmes
    Par yaya.gaga dans le forum Macros et VBA Excel
    Réponses: 8
    Dernier message: 11/11/2014, 20h55
  2. Réponses: 9
    Dernier message: 22/04/2014, 22h15
  3. minimiser mes lignes de codes
    Par salseropom dans le forum C++
    Réponses: 3
    Dernier message: 18/09/2009, 08h48
  4. [netbeans][Linux] Nombre de lignes de codes
    Par sylvain_neus dans le forum NetBeans
    Réponses: 5
    Dernier message: 13/08/2004, 10h09
  5. Calculeur de ligne de code
    Par Bernybon dans le forum Autres éditeurs
    Réponses: 9
    Dernier message: 05/03/2004, 16h29

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo