Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
790 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  C++ et pointeurs, problème pour désalouer...

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

C++ et pointeurs, problème pour désalouer...

n°1871239
burn2
ça rox du poney
Posté le 08-04-2009 à 17:35:52  profilanswer
 

Bonjour à tous et toutes, j'aurais besoin de votre aide pour comprendre le "pourquoi" du comment.
 
Je développe en C++ QT, et j'ai une application principale qui lance un thread de calcul qui va envoyer des signaux à ma fenêtre principale.
Tout ça marche parfaitement.
Bon dans un but d'optimisation, je cherche à supprimer ce que je créais pour ne pas réalouer à chaque fois et perdre en mémoire.
 
Mon programme me permet de rechercher une chaine de caractère dans chaque ligne des documents listés dans un dossier.
 
Voici donc les éléments qui posent problème:
Mon thread la boucle run

Code :
  1. [...]//Diverses choses inutiles dans le contexte puisque pas de pointeur
  2. //Variables
  3. bool contient=false;
  4. int nbOcc=0;
  5. QTableWidgetItem * item1=new QTableWidgetItem("" );//Pas utile je sais mais c'était pour vérifier
  6. QTableWidgetItem * item2=new QTableWidgetItem("" );
  7. foreach (QString s,currentDir.entryList())
  8. {
  9.    [...] //parcour des fichiers
  10.  if (contient)
  11.  {
  12.   char tmp2[33];
  13.   //Création d'une ligne d'enregistrement
  14.   item1=new QTableWidgetItem(s);
  15.   itoa(nbOcc,tmp2,10);
  16.   item2=new QTableWidgetItem(tmp2);
  17.   emit addRow(item1,item2);//Lance addRow du programme principal,Ajout de l'item dans le tableau de la fenêtre principale, le problème peut venir de là.
  18.  }
  19.  emit update();//Juste pour mettre à jour la progressbar
  20. }
  21.            //Le problème est ici! Si je délete item1 et item2, si je relance trop vite en reclicant sur le bouton rechercher, mon application se plante. Si je met en commentaire ces deux lignes ce n'est pas le cas.
  22. delete item1;
  23. delete item2;
  24. emit terminate();//lance finish du programme principal


 
Ma dans mon programme principal, mes slots:

Code :
  1. bool DialogImpl::search()
  2. {
  3. pushButtonRechercher->setEnabled(false);//Je désactive bien le bouton dès le début...
  4. tableResult->clearContents();
  5. for (int i=tableResult->rowCount()-1; i >= 0; --i)
  6.   tableResult->removeRow(i);
  7. m_recherche= new Recherche (m_rep,this,lineEditText->text());
  8. m_recherche->start();
  9. //m_progress.hide();
  10. return true;//pas propre je sais, reste d'une ancienne bidouille
  11. }
  12. void DialogImpl::finish()
  13. {
  14. m_progress.hide();
  15. m_recherche->wait();
  16. pushButtonRechercher->setEnabled(true);
  17. delete m_recherche;//avec ou sans ça ça ne change pas le problème de crash
  18. }
  19. void DialogImpl::addRow(QTableWidgetItem * item1,QTableWidgetItem * item2)
  20. {
  21.   int row=tableResult->rowCount();
  22.   tableResult->insertRow(row);
  23.   tableResult->setItem(row,0,item1);
  24.   tableResult->setItem(row,1,item2);
  25. }


Si j'enlève les:
delete item1;
delete item2;
plus de plantage, ma question est pourquoi donc?
Je précise qu'avec les delete ça marche quand même, mais si je clique trop rapidement sur le bouton rechercher du genre "mode bourin à cliquer moulte fois :D" l'application se crash, alors que sans les delete non. Est ce grave de ne  pas désalouer? Les news désalouent ils les anciennes valeurs?


Message édité par burn2 le 08-04-2009 à 17:43:26

---------------
"C'est vrai qu'un type aussi pénible de jour on serait en droit d'espérer qu'il fasse un break de nuit mais bon …"
mood
Publicité
Posté le 08-04-2009 à 17:35:52  profilanswer
 

n°1871249
burn2
ça rox du poney
Posté le 08-04-2009 à 17:42:13  profilanswer
 

Une petite question d'ailleurs, en admetons que ça soit possible.
Si je fais:

Code :
  1. int * test;
  2. test=new int (10);
  3. test=new int (15);


Entre les deux new, la mémoire est elle bien désalouée ou il faut que je fasse un delete test?


Message édité par burn2 le 08-04-2009 à 17:42:31

---------------
"C'est vrai qu'un type aussi pénible de jour on serait en droit d'espérer qu'il fasse un break de nuit mais bon …"
n°1871270
Joel F
Real men use unique_ptr
Posté le 08-04-2009 à 17:57:57  profilanswer
 

v_v on est pas en java. 1 new = 1 delete.
 
et tu sais que new int(10) construir *1* int qui vaut 10 et pas 10 int :o

n°1871276
burn2
ça rox du poney
Posté le 08-04-2009 à 18:42:31  profilanswer
 

Oui je sais, mais là c'était une question avec l'exemple le plus "pourite" possible pour bien être sûr.
 
Sinon dans mon code alors c'est quoi qui cloche, pourquoi si je met le delete ça ne marche plus instantanément??? :??:


---------------
"C'est vrai qu'un type aussi pénible de jour on serait en droit d'espérer qu'il fasse un break de nuit mais bon …"
n°1871287
Joel F
Real men use unique_ptr
Posté le 08-04-2009 à 19:31:44  profilanswer
 

la question ets de savoir si addrow ne transfere pas l'ownership des objets au conteneru, ce qui fait que lorsque le conteneur est detruit, il fait le delete deja.
 
Rajoute un if(item1) delet item1; pour voir

n°1871288
burn2
ça rox du poney
Posté le 08-04-2009 à 19:34:30  profilanswer
 

Oui c'est ce que je me disais, mais le problème, c'est que ça se crash au tout début du relancement, je n'ai même pas le temps de voir la bare de chargement que vlam. Et le delete est totalement à la fin du processus après avoir parcourus tous les fichier, donc avoir vu la bare de progression et qu'elle soit arrivée à 100%. Donc ce n'est pas possible. Là ça se crashe au premier tour de boucle au relancement visiblement.  
il faudrait que je me mette en mode debug pour suivre ou ça crash, mais j'aimerais bien en avoir la cause.  
Pour moi c'est dans le thread au relancement que ça se crash et non pas ailleurs.
 
Or comme vous pouvez le constater je ne peux recliquer sur le bouton pour relancer que quand le thread est bien terminé et que tout est bien stoppé. Donc j'avoue ne pas comprendre pourquoi si je vais trop vite ça crash, mais si j'attends un tout petit moment ça passe.  
 
 
EDIT: ça le fait autant sous xp que sous vista, par contre sous vista j'ai une protection contre la prévention des données, je me demande si ce n'est pas une protection de l'os contre un "je désaloue via delete, et j'alloue rapidement sans new par un programme en un temps trop rapide".


Message édité par burn2 le 08-04-2009 à 19:40:40

---------------
"C'est vrai qu'un type aussi pénible de jour on serait en droit d'espérer qu'il fasse un break de nuit mais bon …"
n°1871307
burn2
ça rox du poney
Posté le 08-04-2009 à 21:13:55  profilanswer
 

Joel F a écrit :

v_v on est pas en java. 1 new = 1 delete.
 
et tu sais que new int(10) construir *1* int qui vaut 10 et pas 10 int :o


Et bien non, en fait ce que tu dis est totalement faux....
Un test tout c**:
int *test;
while (1)
test = new int (10);
 
regarde l'utilisation de ta ram...
 
Bon par contre j'ai peut-être une idée de mon pb et pourquoi j'avais pas de fuite mémoire sans delete que j'ai de toute façon mal placé là...


---------------
"C'est vrai qu'un type aussi pénible de jour on serait en droit d'espérer qu'il fasse un break de nuit mais bon …"
n°1871311
Joel F
Real men use unique_ptr
Posté le 08-04-2009 à 21:40:40  profilanswer
 

je pense que non. Si t'arrive à voir l'effet d'une allocation de 4 octets dans ton moniteur de ram t'es super fort meme comme ça.
 
Alloue en boucle 1Mo et on en reparle

n°1871315
xilebo
noone
Posté le 08-04-2009 à 21:44:46  profilanswer
 

burn2 a écrit :


Et bien non, en fait ce que tu dis est totalement faux....
Un test tout c**:
int *test;
while (1)
test = new int (10);
 
regarde l'utilisation de ta ram...
 
Bon par contre j'ai peut-être une idée de mon pb et pourquoi j'avais pas de fuite mémoire sans delete que j'ai de toute façon mal placé là...


 
 
joli memory leak que voilà. Tu alloues en boucle sans désallouer. Bien sur, 4 octets par 4 octets tu vas mettre longtemps à la remplir. Comme le dit Joel F : un new = un delete TOUJOURS.
 

n°1871320
el muchach​o
Comfortably Numb
Posté le 08-04-2009 à 22:33:37  profilanswer
 

Et pour ce qui est des objets, les désallocations dans le sens inverse des allocations pour éviter les bugs dûs à d'éventuelles dépendances entre objets (surtout quand il y a du nettoyage dans les destructeurs).
ex: si une classe initialise une ressource et clôt la ressource dans son destructeur, et qu'une autre classe peut utiliser la ressource une fois ouverte, on construit la première classe, puis la 2e, mais la destruction devra se faire dans le sens inverse des new.


Message édité par el muchacho le 08-04-2009 à 22:37:49

---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
mood
Publicité
Posté le 08-04-2009 à 22:33:37  profilanswer
 

n°1871321
Joel F
Real men use unique_ptr
Posté le 08-04-2009 à 22:43:07  profilanswer
 

ouais enfin là c'est que tu as violé le principe d'inversion de responsabilité et de propriété.

n°1871323
jesus_chri​st
votre nouveau dieu
Posté le 08-04-2009 à 22:53:36  profilanswer
 

Joel F a écrit :

la question ets de savoir si addrow ne transfere pas l'ownership des objets au conteneru, ce qui fait que lorsque le conteneur est detruit, il fait le delete deja.
 
Rajoute un if(item1) delet item1; pour voir


delete teste déjà si le pointeur est NULL, comme free(), pas besoin de le tester en ammont
if( p ) delete p;
est équivalent mais redondant face à simplement :
delete p;
 
et c'est standard, ça ne dépend pas de l'implémentation.

n°1871324
Joel F
Real men use unique_ptr
Posté le 08-04-2009 à 22:56:05  profilanswer
 

je la note celle là :) merci

n°1871353
burn2
ça rox du poney
Posté le 09-04-2009 à 08:40:41  profilanswer
 

Joel F a écrit :

je pense que non. Si t'arrive à voir l'effet d'une allocation de 4 octets dans ton moniteur de ram t'es super fort meme comme ça.
 
Alloue en boucle 1Mo et on en reparle


Et pourtant, je le vois bien sur mon moniteur system. Vu la vitesse de la ram c'est parfaitement normal...  
Avec cette boucle j'alloue une infinitée d'entier, car un new!=delete, donc le précédent int déclaré est toujours valable!
Du coup en boucle infinie ça se remplie très très rapidement! (du genre une pente à 45% et la ram qui se remplie jusqu'a 80% de 2go en 2/3s maximum. Je vous ferais un screen.
 
Je vois la ram se remplir quasi totalement, je n' pas laissé jusqu'au bout, mais teste et tu verras qu'il faut pour chaque new un delete sans quoi la précédente variable pointée n'est pas détruite...


Message édité par burn2 le 09-04-2009 à 08:48:18

---------------
"C'est vrai qu'un type aussi pénible de jour on serait en droit d'espérer qu'il fasse un break de nuit mais bon …"
n°1871354
burn2
ça rox du poney
Posté le 09-04-2009 à 08:41:04  profilanswer
 

xilebo a écrit :


 
 
joli memory leak que voilà. Tu alloues en boucle sans désallouer. Bien sur, 4 octets par 4 octets tu vas mettre longtemps à la remplir. Comme le dit Joel F : un new = un delete TOUJOURS.
 


Si c'est le cas alors j'avais très mal compris son oui, car je l'avais pris par un new = delete et il n'y a pas besoin d'en faire entre.

jesus_christ a écrit :


delete teste déjà si le pointeur est NULL, comme free(), pas besoin de le tester en ammont
if( p ) delete p;
est équivalent mais redondant face à simplement :
delete p;
 
et c'est standard, ça ne dépend pas de l'implémentation.


pas sûr! Si tu fais:
int * test ;
test= new int(10);
delete test;
delete test;
au deuxième délete ça va se cracher!
 
 
Par contre je pense avoir trouvé la cause de mon problème, dixit ce que m'a dit un pote et avec cette info, j'ai une idée du problème... Je teste ça dessuite.

Message cité 1 fois
Message édité par burn2 le 09-04-2009 à 08:46:38

---------------
"C'est vrai qu'un type aussi pénible de jour on serait en droit d'espérer qu'il fasse un break de nuit mais bon …"
n°1871357
xilebo
noone
Posté le 09-04-2009 à 08:49:01  profilanswer
 

burn2 a écrit :


pas sûr! Si tu fais:
int * test ;
test= new int(10);
delete test;
delete test;
au deuxième délete ça va se cracher!
 
 
Par contre je pense avoir trouvé la cause de mon problème, dixit ce que m'a dit un pote et avec cette info, j'ai une idée du problème... Je teste ça dessuite.


 
Ce n'est pas ce qu'il a dit.
 
Tu n'as pas besoin de tester si ton pointeur est NULL. Par contre, quand tu fais un delete sur un pointeur, le delete (ou le free) ne change pas la valeur du pointeur (accessoirement ici, tu aurais rajouté le test que ça n'aurait rien changé.). Ainsi, si tu rappelles delete derrière sur le même pointeur -> comportement indéterminé.
 
Généralement, après un delete ou un free, on met le pointeur à NULL.
 


Message édité par xilebo le 09-04-2009 à 08:50:01
n°1871359
burn2
ça rox du poney
Posté le 09-04-2009 à 08:54:15  profilanswer
 

Bon en fait ce n'est même pas le même problème que je pensais.  
L'idée que j'avais et que m'avait donné un collègue c'était que dans le tableau, le clear delete tout seul les espaces alouées. Et en fait en l'enlevant le problème est le même.  
 
Concrètement, le problème que j'ai après avoir testé:
Si j'enlève mon clear, laisse les deux deletes à la fin (inutile mais bon je voudrais comprendre pourquoi), le programme se plante toujours à la 3ème exécution de la fonction. Toujours à la 3ème.
Je continue mes tests pour comprendre un peu plus...


---------------
"C'est vrai qu'un type aussi pénible de jour on serait en droit d'espérer qu'il fasse un break de nuit mais bon …"
n°1871360
Joel F
Real men use unique_ptr
Posté le 09-04-2009 à 09:00:07  profilanswer
 

Putain mais quand je dis 1 new = 1 delete, ca veut dire qu'il faut faire un delete pour chaque new [:prozac]
 
TOn probleme viens que ton conteneur doit prendre la propriété des pointeurs et les delet lui même sans les mettre à NULL. Quant tu passes dessus avec les tiens, tu desalloue n'imp.

n°1871361
burn2
ça rox du poney
Posté le 09-04-2009 à 09:00:24  profilanswer
 

Bon j'ai isolé le problème:
J'ai testé avec:
delete item1;
item1=NULL;
delete item2;
item2=NULL;
 
Le problème ne change pas, par contre je viens de comprendre un truc:
En fait le problème vient de là:

Code :
  1. for (int i=tableResult->rowCount()-1; i >= 0; --i)
  2.   tableResult->removeRow(i);


automatiquement, la boucle désaloue les items et les delete ce qui explique que je n'ai pas de fuite de mémoire dans mon programe sans les deletes. Si j'enlève cette partie, je n'ai plus le plantage.
 
Ce que je ne comprend pas, c'est pourquoi malgrès mon ajout du pointeur null, pourquoi ça se plante toujours à la 3ème exécution même si je delete deux fois un pointeur puisque delete teste si c'est null selon vous. (pour quoi ça repasse la 2ème en fait dans le cas ou c'est une question de pointeur pas passé à null)

Joel F a écrit :

Putain mais quand je dis 1 new = 1 delete, ca veut dire qu'il faut faire un delete pour chaque new [:prozac]
 
TOn probleme viens que ton conteneur doit prendre la propriété des pointeurs et les delet lui même sans les mettre à NULL. Quant tu passes dessus avec les tiens, tu desalloue n'imp.


Tu conviendras que c'était ambigüe tout de même :D
 
Oui le conteneur désaloue tout seul en fait, mais ce que je ne comprend pas c'est pourquoi ça passe 2 fois mais pas 3?  
 


Message édité par burn2 le 09-04-2009 à 09:02:47

---------------
"C'est vrai qu'un type aussi pénible de jour on serait en droit d'espérer qu'il fasse un break de nuit mais bon …"
n°1871365
burn2
ça rox du poney
Posté le 09-04-2009 à 09:15:57  profilanswer
 

Cela dit, je ne sais toujours pas pourquoi ça cloche. :/
 
Bilan du topic:
J'ai avancé un peu, j'ai compris que tableResult->removeRow(i); deleté tout seul les items donc il est inutile de les supprimer de l'autre côté, mais ma question, c'est même si c'est inutile pourquoi ça se plante à la 3ème et pas la deuxième.
Si c'était une histoire de pointeur pas passé à null dans la fonction de QT automatique, ça ne marcherait même pas à la 2ème. Cela dit tampis, j'ai revus le principe du pointeur ça m'a bien raffraichie les idées (des notions ou je commençais à avoir des doutes puisque plus trop pratiqué) et je sais qu'il faudra que je fasse gaf avec qt à chaque pointeur passé car lui le désalouera tout seul à la suppression...


Message édité par burn2 le 09-04-2009 à 09:16:55

---------------
"C'est vrai qu'un type aussi pénible de jour on serait en droit d'espérer qu'il fasse un break de nuit mais bon …"
n°1871481
Joel F
Real men use unique_ptr
Posté le 09-04-2009 à 12:53:07  profilanswer
 

fais gaffe, pas sur que ca soit le cas pour tout les objets QT. La doc *doit* te el dire si oui ou non il y a ownership transfer

n°1871517
burn2
ça rox du poney
Posté le 09-04-2009 à 13:56:10  profilanswer
 

Ouep je vérifierais. Mais bon j'essayais de comprendre comment ça pouvait passer deux fois d'affiler sans planter et planter la 3ème, et là je pense que le mystère reste entier. :D
 
Par contre je te conseille de tester mon while, car je peux t'assurer que ça remplis trés trés vite la mémoire. :D (pareil que les forks ou là par contre on peut aussi écrouler l'os :D)


---------------
"C'est vrai qu'un type aussi pénible de jour on serait en droit d'espérer qu'il fasse un break de nuit mais bon …"
n°1871546
Joel F
Real men use unique_ptr
Posté le 09-04-2009 à 14:24:45  profilanswer
 

pour le while je sais merci, c'ets ce que je disasi au debut [:dawa]

n°1871649
burn2
ça rox du poney
Posté le 09-04-2009 à 16:08:41  profilanswer
 

Joel F a écrit :

pour le while je sais merci, c'ets ce que je disasi au debut [:dawa]


Tes propos sont contradictoires alors:

Joel F a écrit :

je pense que non. Si t'arrive à voir l'effet d'une allocation de 4 octets dans ton moniteur de ram t'es super fort meme comme ça.
 
Alloue en boucle 1Mo et on en reparle



---------------
"C'est vrai qu'un type aussi pénible de jour on serait en droit d'espérer qu'il fasse un break de nuit mais bon …"
n°1871684
Joel F
Real men use unique_ptr
Posté le 09-04-2009 à 17:09:28  profilanswer
 

sauf que la on se comprenait pas : je pensais que tu disais le contraire de ce que je disais sauf que tu disais l'inverse

n°1871713
burn2
ça rox du poney
Posté le 09-04-2009 à 17:40:03  profilanswer
 

Je pense qu'on n'est pas sur la bonne onde, ceci explicant qu'on pense comprendre le contaire de l'autre. :D Mais bon ce qui importe c'est qu'on se comprenne au final. :D
Bon en tout cas merci de votre aides. Même si je ne saurais jamais pourquoi ça déconner toujours à la 3ème fois...


Message édité par burn2 le 09-04-2009 à 17:40:39

---------------
"C'est vrai qu'un type aussi pénible de jour on serait en droit d'espérer qu'il fasse un break de nuit mais bon …"
n°1871957
Glock 17Pr​o
Posté le 10-04-2009 à 12:40:21  profilanswer
 

Joel F a écrit :

 je pensais que tu disais le contraire de ce que je disais sauf que tu disais l'inverse


c bon ça

mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  C++ et pointeurs, problème pour désalouer...

 

Sujets relatifs
Probleme de syntaxe pour envoyer une chaine vers une fonction javascri[C] Initialisation d'un tableau constant
Probléme SocketProblème macro propriétés masse SolidWorks
[Oracle Forms] Problème de cachehibernate problème
[C] Parser un fichier texte[C - librairie Gtk] mettre en place une GtkListStore
Probléme avec java.lang.Runtime 
Plus de sujets relatifs à : C++ et pointeurs, problème pour désalouer...


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR