Pointeurs changent de valeur 'seuls' [Résolu]

Messages postés
47
Date d'inscription
samedi 7 janvier 2006
Statut
Membre
Dernière intervention
13 décembre 2012
- - Dernière réponse : wilvart
Messages postés
47
Date d'inscription
samedi 7 janvier 2006
Statut
Membre
Dernière intervention
13 décembre 2012
- 29 juin 2012 à 14:12
Bonjour,

J'ai un très gros soucis de pointeur. Mon code sert à traiter une image. J'y ai trouvé plusieurs blocs representant des lignes ou bout de lignes (du texte) que je voudrais lier afin d'avoir la phrase entière.

Ma variable 'lines' me permet de stocker toutes mes lignes, une ligne étant composée de plusieurs blocs.

Dans le code ci dessous, j'ai simplifié les choses (je vais pas vous faire lire mes 10k de lignes..) en ciblant le problème.

Dans la trace, vous remarquerez que les adresses de mes lignes changent. C'est ce que je voudrais comprendre. Dans la suite de mon algo, j'utilise des pointeurs vers ces lignes, donc si l'adresse change, segfault et autres joyeuseries s'invite dans mon shell :D

(J'utilise la librairie opencv sous mac)

void ReceiptSection::createLines (std::vector<std::vector<cv::Rect*> >& lines, cv::Rect& currentLetter)
{
     lines.push_back( std::vector<cv::Rect*>());
     std::vector<cv::Rect*>& newLine = lines.back();
     newLine.push_back(&currentLetter);
     LOG("---------------- PTR lines.back : " << &(lines.back()), 3);
     cv::rectangle(_sectionImage, cv::Point(currentLetter.x, currentLetter.y), cv::Point(currentLetter.x+currentLetter.width, currentLetter.y + currentLetter.height), cv::Scalar(0), 2);
}




void ReceiptSection::main()
{
    std::vector<std::vector<cv::Rect*> > lines;

    // _extractedLetters est un attribut de ma classe correctement rempli
    // std::vector<cv::Rect> _extractedLetters;
    std::vector<cv::Rect>::iterator aLetterIt = _extractedLetters.begin();

    do
    {
LOG("---------------- Before createLines", 3);
displayLinesPtr(lines);

createLines(lines, *aLetterIt);

LOG("---------------- After createLines", 3);
displayLinesPtr(lines);

aLetterIt++;
   }
   while (aLetterIt != _extractedLetters.end());




void ReceiptSection::displayLinesPtr(const std::vector<std::vector<cv::Rect*> >& lines)
{
    LOG("----------------------------LinesPtr---------------------------", 3);

    int cpt=1;

    for(std::vector<std::vector<cv::Rect*> >::const_iterator lineIt=lines.begin(); lineIt!=lines.end(); ++lineIt, cpt++)
    {
    	LOG("ptrLines " << cpt << " = " << &(*lineIt), 3);
    }

    LOG("---------------------------------------------------------------", 3);
}





Enfin, voici la trace que j'obtiens lors du traitement d'une image contenant plusieurs blocs.
Comme je vous le disais, ce code est une version simplifié qui n'a pour but que de reproduire l'erreur à laquelle je suis confronté.



<receiptSection.cpp:370> ---------------- Before createLines
<receiptSection.cpp:942> ----------------------------LinesPtr---------------------------
<receiptSection.cpp:951> ---------------------------------------------------------------
<receiptSection.cpp:1145> ---------------- PTR lines.back : 0x10115aa50

<receiptSection.cpp:373> ---------------- After createLines
<receiptSection.cpp:942> ----------------------------LinesPtr---------------------------
<receiptSection.cpp:948> ptrLines 1 = 0x10115aa50
<receiptSection.cpp:951> ---------------------------------------------------------------

<receiptSection.cpp:370> ---------------- Before createLines
<receiptSection.cpp:942> ----------------------------LinesPtr---------------------------
<receiptSection.cpp:948> ptrLines 1 = 0x10115aa50
<receiptSection.cpp:951> ---------------------------------------------------------------
<receiptSection.cpp:1145> ---------------- PTR lines.back : 0x10115a838

<receiptSection.cpp:373> ---------------- After createLines
<receiptSection.cpp:942> ----------------------------LinesPtr---------------------------
<receiptSection.cpp:948> ptrLines 1 = 0x10115a820
<receiptSection.cpp:948> ptrLines 2 = 0x10115a838
<receiptSection.cpp:951> ---------------------------------------------------------------



Merci d'avance !
Afficher la suite 

5 réponses

Meilleure réponse
Messages postés
3801
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
15 novembre 2019
90
3
Merci
Bonjour.

Tout d'abord, je te déconseille l'usage d'un std::vector de std::vector. C'est généralement pas terrible. Un boost::multi_array est plus adapté. On peut aussi créer un std::vector à une seule dimension de taille N*N et feinter à l'usage en appelant "[x * size + y]" au lieu de "[x][y]".
Néanmoins, si tu ne veux pas de dépendance à boost ou ne pas réécrire ton code (ce qui est compréhensible), dans ce cas, fais au moins attention à une chose:
Un std::vector n'a pas ses éléments fixe en mémoire !

En effet, il y a une optimisation qui consiste à doubler la taille de la capacité si la taille venait à dépasser cette capacité.
Ex:
Si tu insère un 2+ éléments, la taille est de 2+, mais la capacité est de 4.
Si tu insère un 4+ éléments, la taille est de 4+, mais la capacité est de 8.
Si tu insère un 8+ éléments, la taille est de 8+, mais la capacité est de 16.
etc...

Ça évite de refaire une allocation à chaque ajout d'élément. Le souci, c'est que ça te fais croire, à tord que la zone mémoire est toujours la même (surtout quand tu as beaucoup d'éléments, vu que tu ne réalloues pas souvent).
Il faut savoir que si en augmentant la capacité, il n'y a pas assez de place en mémoire pour avoir tes éléments de manière contigües, alors realloc est utilisé (ce qui change la zone mémoire).

En d'autre terme, tu ne peux absolument pas prendre l'adresse d'un élément dans un std::vector !
On ne fait jamais de "std::vector<T>" en prenant l'adresse de T, celle-ci pouvant changer en cas d'ajout ou de suppression d'élément dans le tableau.
Pour résoudre ton problème, tu peux tout à fait faire un std::vector<std::vector<cv::Rect*>*>. Si le pointeur change de place, ce n'est pas grave, car il pointera toujours sur la zone que tu veux.

(J'utilise la librairie opencv sous mac)

Bibliothèque, merci :)

________________________________________________________________________
Historique de mes créations, et quelques articles:
[ http://0217021.free.fr/portfolio http://0217021.free.fr/portfolio]
Merci d'utiliser Réponse acceptée si un post répond à votre question

Dire « Merci » 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources 191 internautes nous ont dit merci ce mois-ci

Commenter la réponse de cptpingu
Messages postés
3801
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
15 novembre 2019
90
3
Merci
Du coup la solution la moins couteuse en temps (pour ce projet) est belle et bien de faire un std::vector<std::vector<cv::Rect*>*> et par conséquent de gérer la mémoire de façon un peu plus hard.

J'ai oublié de préciser que tu auras de bien meilleures performances en utilisant un pointeur sur "std::vector", vu qu'en cas de réallocation, tu ne copieras que le pointeur et non tous les (gros) sous tableaux. De plus, les pointeurs étant bien moins gros que les vecteurs, tu auras beaucoup moins de chance d'avoir un déplacement mémoire en cas de realloc.
Il est possible que tu constates une amélioration à ce niveau là.

Je ne connais pas la différence, pour moi tout est une lib/framework/biblio/... :D

- Une bibliothèque est un fichier compilé contenant des fonctions prêtes à être utilisé par un autre exécutable.
- Une librairie est un magasin où on achète des livres (rien à voir avec du code, mais les gens traduisent "library" incorrectement... C'est un "faux-ami" anglais.)
- Un framework n'est pas forcément un code compilé, ça peut être une suite d'outils, de fonction et/ou de bibliothèque qui te facilitent la vie, mais t'oblige à suivre une direction bien précise. Par exemple Qt est un framework qui te permet de développer des
applications graphiques, mais tu auras alors besoin de toutes la suite d'outils fournis avec pour que ça fonctionne (qmake, par exemple).

Merci beaucoup de ton aide !

Je t'en prie. N'hésite pas si tu as d'autre question.

________________________________________________________________________
Historique de mes créations, et quelques articles:
[ http://0217021.free.fr/portfolio http://0217021.free.fr/portfolio]
Merci d'utiliser Réponse acceptée si un post répond à votre question

Dire « Merci » 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources 191 internautes nous ont dit merci ce mois-ci

Commenter la réponse de cptpingu
Messages postés
47
Date d'inscription
samedi 7 janvier 2006
Statut
Membre
Dernière intervention
13 décembre 2012
0
Merci
Merci beaucoup de ton aide !

Effectivement, je n'aurais pas du utiliser de std::vector... Je suis prévenu pour la prochaine fois !

Du coup la solution la moins couteuse en temps (pour ce projet) est belle et bien de faire un std::vector<std::vector<cv::Rect*>*> et par conséquent de gérer la mémoire de façon un peu plus hard.

[quote](J'utilise la librairie opencv sous mac)

Bibliothèque, merci :) /quote

Je ne connais pas la différence, pour moi tout est une lib/framework/biblio/... :D


Encore merci !!!
Commenter la réponse de wilvart
Messages postés
1137
Date d'inscription
lundi 17 novembre 2003
Statut
Membre
Dernière intervention
23 janvier 2016
17
0
Merci
Salut,

Des réponses aussi claires, ça fait réver !

Bye...
Commenter la réponse de yann_lo_san
Messages postés
47
Date d'inscription
samedi 7 janvier 2006
Statut
Membre
Dernière intervention
13 décembre 2012
0
Merci
:D
Commenter la réponse de wilvart