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++ Discussion :

comment gérer un retour pointeur de pointeur et methode d'assignement si retour est NULL


Sujet :

C++

  1. #1
    Membre du Club
    Profil pro
    Developer
    Inscrit en
    Juin 2004
    Messages
    194
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Developer

    Informations forums :
    Inscription : Juin 2004
    Messages : 194
    Points : 58
    Points
    58
    Par défaut comment gérer un retour pointeur de pointeur et methode d'assignement si retour est NULL
    Bonjour,

    Voici un bout de code, utlisant en interne la STL, qui demande un check avant assignation
    d'un pointeur et sachant qu'il y a dereferencement il faut tester que le pointeur n'est pas null.


    Mais est ce que la manière ci-dessous (//2. dans la fonction UpdateTracerset()) est la bonne méthode ?


    /*functions et header*/
    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
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
     
    	/*rawcorner.h*/
     
    	// an_rawcorner_alloc()
    	inline unsigned char *an_rawcorner_alloc()
    	{
    		return (unsigned char *)calloc(sizeof(char),RAWCORNER_TOTAL_SIZE);
    	}
     
     
     
    	/*cornerlist.h*/
     
    	// -------------------------------
    	//  Title   : get_first
    	//  Descript: gives a pointer to the first corner data of the list 
    	//            and initializes the internal pointer to the first corner
    	//	IN		: nothing
    	//	OUT		: nothing
    	//	Return  : pointer to the pointer to the data of the first corner
    	//			  NULL if the list is empty
    	// ------------------------------------------
    	virtual unsigned char **get_first()=0;
     
    	// ---------------------
    	//  Title   : get_next
    	//  Descript: gives a pointer to the next corner data of the list 
    	//	IN		: nothing
    	//	OUT		: nothing
    	//	Return  : pointer to the pointer to the data of the next corner
    	//			  NULL if at the end of the list, or list empty or internal pointer not initialized
    	// -----------------------------------------------
    	virtual unsigned char **get_next()=0;
     
    	Ccornerlist_Int (){..};
    /*// Wrapper interne dll (tracer_tool.cpp) */
    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
    17
    18
    19
    20
    21
    22
     
    	/*tracer.cpp*/
     
    	// Wrapper to internal dll 
     
    	DLL(long) update_tracer_set(void** tracerInstance, CCornerList_Int* newCornerList,unsigned char * currentCorner)
    {
     
    	int returnValue = 0;
     
    	if (*tracerInstance!=NULL){
    		static_cast<TracerTool*>(*tracerInstance)->updateTracerSet(newCornerList, currentCorner);
    		returnValue = 0;
    	}
    	else {
     
    		returnValue = -2;
    	}
     
    	return returnValue; 
     
    };

    /* call */
    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
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
     
    	/*call.cpp*/
     
    	//function
    	// write fixed data in a corner struct in function of label_id
    	void fill_corner(unsigned char *rawCorner,int labelID, int x0_bbox, int y0_bbox, int x1_bbox, int y1_bbox, int trackingID)
    	{
    		vgt_an_rawcorner_set_long(rawCorner,LABEL_ID_L,labelID);
     
    		an_rawcorner_set_long(rawCorner,BBOX_X0_L,x0_bbox); 
    		an_rawcorner_set_long(rawCorner,BBOX_Y0_L,y0_bbox); 
    		an_rawcorner_set_long(rawCorner,BBOX_X1_L,x1_bbox);
    		an_rawcorner_set_long(rawCorner,BBOX_Y1_L,y1_bbox);
     
    		an_rawcorner_set_long(rawCorner,TRACKING_ID_L,trackingID);// identifier (-1=unknown)
    	}
     
    	//extract cornerlist
    	Ccornerlist_Int* cornerlistExtracted						= NULL;
    	cornerlistModule.create_obj_cornerlist(&cornerlistExtracted);
     
    	unsigned char* corner2			                    		= an_rawcorner_alloc();
     
    	fill_corner(corner2, 1,320,19,350,49,7);
    	//add to cornerlist
    	cornerlistExtracted->add(corner2);
     
    	fill_corner(corner2, 2,160,8,175,24,8);
    	//add to cornerlist
    	cornerlistExtracted->add(corner2);
     
     
    	corner2 = *(cornerlistExtracted->get_first());  //est ce la bonne méthode ?
     
    	pCtracer->update_tracer_set(&tracerInstance, cornerlistExtracted,corner2);
     
    	...
    Enfin la dll interne ou se trouve le bug
    /* DLL interne */
    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
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
     
    	/*tracer_tool.cpp*/
     
    void Tracertool::updateTracerSet(CCornerList_Int* newCornerList, unsigned char * currentCorner){
     
    	// reset the update status of all the (simple) corners
    	map<int, SimpleCorner* >::iterator itSimpleCornerList;
    	for (itSimpleCornerList = SimpleCornerList.begin(); itSimpleCornerList!=SimpleCornerList.end(); itSimpleCornerList++){		
    		(*itSimpleCornerList).second->isUpdated = false;	
    		(*itSimpleCornerList).second->timeElapsedSinceLastUpdate++;
     
    	}
     
    	// for all the current corners
    	//unsigned char *currentCorner = newCornerList->get_first();
    	//unsigned char **currentCorner = vgt_an_rawcorner_alloc();
    	//unsigned char *currentCorner = vgt_an_rawcorner_alloc();
     
    //	strcpy((char*)currentCorner,(const char*) newCornerList->get_first()) ;
    	printf("a. value of newCornerList->get_first() =%p\n",newCornerList->get_first());
        currentCorner=*(newCornerList->get_first());
    	printf("b. value of currentCorner after assign =%p\n",currentCorner);
     
    	while (currentCorner !=NULL){
     		//int trackingID = currentCorner->tracking_id;
    		long trackingID =0;
     		vgt_an_RawCorner_get_long(currentCorner,TRACKING_ID_L,&trackingID);
     
     		// search corresponding simple corner
     		map<int, SimpleCorner* >::iterator itcornerTracer= this->SimpleCornerList.find(trackingID);
    		// if it exists
    		if (itcornerTracer!=SimpleCornerList.end()){		
    			(*itcornerTracer).second->isUpdated = true;
    			(*itcornerTracer).second->timeElapsedSinceLastUpdate = 0;
    			// if the corner exist for a number of frame >= MAX_TRACER_SIZE 
    			if ((*itcornerTracer).second->tracer.size() >= (*itcornerTracer).second->tracer_MAX_SIZE ){ 
     
    				//erease first element of real tracer
    				delete (*(*itcornerTracer).second->tracer.begin());
    				(*itcornerTracer).second->tracer.erase( (*itcornerTracer).second->tracer.begin() );
     
    			}
     
    			//addPointTotracer(currentCorner,(*itcornerTracer).second );
    			addPointTotracer(currentCorner,(*itcornerTracer).second );
    			//addPointToSmoothtracer(currentCorner,(*itcornerTracer).second, 3);			
    			addPointToSmoothtracer(currentCorner,(*itcornerTracer).second, 3);			
    		}
    		// else create new simple corner
    		else{
    			SimpleCorner* newcorner = new SimpleCorner();
    			newcorner->isUpdated=true;
    			newcorner->timeElapsedSinceLastUpdate=0;
    			// add the corner to the intern  list
    			this->SimpleCornerList.insert(pair<int, SimpleCorner*>(trackingID, newcorner));
    		}
     
    		//1.
    		//currentCorner=*(newCornerList->get_next()); !! ACCESS VIOLATION QUAND FONCTION RETOURNE NULL
     
    		//2.
    		//est ce une solution acceptable pour tester la condition NULL ? 
    		unsigned char ** temp=newCornerList->get_next();
    		if(temp!=0)
    			currentCorner=temp;
    		else
    			currentCorner = NULL;
     
    		//3. Ou l'utilisation de strcpy ?  
    		//strcpy((char*)currentCorner,(const char*)newCornerList->get_next()) ;
     
    	}
     
     
    };
    Dans mon call la ligne:
    corner2 = *(cornerlistExtracted->get_first());
    ne genere pas d'erreur par contre le ->get_next() bien .

    Le bug est dans la fonction updateTracerSet et j'hesite entre différentes solutions possibles , quelle est une autre meilleure solution?

    Merci

  2. #2
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    Dés le moment où tu travailles avec des pointeurs, il est toujours possible de tester la non nullité du pointeur, et ce, même si c'est un pointeur de pointeur, un pointeur de pointeur de pointeur ou ... on pourrait continuer longtemps comme ca

    Par contre :

    Si ton pointeur (de pointeur) est récupéré depuis une fonction quelconque, il faudra, bien évidemment, avoir la certitude que cette fonction renvoie un pointeur NULL quand les conditions sont remplies.

    Cela implique, fatalement, qu'il faudra veiller à ce que les données sous-jascentes soient correctement gérées (que le pointeur soit initialisé à NULL tant que l'on n'a pas un pointeur correct, et qu'il soit remis à NULL dés qu'il est invalidé).

    Le tout, sans oublier qu'il faut avoir la certitude que le pointeur au départ duquel tu essayes d'appeler la fonction membre soit, bien évidemment, lui aussi valide

    Ceci dit, je dois avouer être un peu surpris que tu parte sur l'idée de jouer avec des pointeurs (et pire, des pointeurs de pointeurs) sur void pour certaines de tes fonctions...

    A moins que tu ne doive t'interfacer avec du C, le pointeur sur void est rarement la solution préférable en C++
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #3
    Membre du Club
    Profil pro
    Developer
    Inscrit en
    Juin 2004
    Messages
    194
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Developer

    Informations forums :
    Inscription : Juin 2004
    Messages : 194
    Points : 58
    Points
    58
    Par défaut
    Oui exact,
    effectivement je dois interfacer avec du C, c'est pourquoi aussi j'utilise
    des pointeurs de pointeurs.

    une bonne solution était de faire ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
         unsigned char** ret = newCornerList->get_next();
         if (ret == NULL) {
                currentCorner = NULL;
         }
         else {
              // dereferencer
                 currentCorner=*(ret);
          }
    au lieu de :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    		//2.
    		unsigned char ** temp=newCornerList->get_next();
    		if(temp!=0)
    			currentCorner=temp;
    		else
    			currentCorner = NULL;
    Mais pour finir je ne passe plus le pointeur de pointeur comme paramètre
    dans ce cas la fonction updateTracerSet devient plus simple a gerer :
    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
    17
    18
     
    void Tracertool::updateTracerSet(CCornerList_Int* newCornerList){
    ..
     
    	// for all the current corner
    	unsigned char** currentCorner = newCornerList->get_first();	
    	while (currentCorner !=NULL){
     
     
     
            ......
     
     
     
           	currentCorner = newCornerList->get_next();
            }
     
    };

    Merci

  4. #4
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,
    Le fait de devoir s'interfacer avec du C permet quand même d'encapsuler les pointeurs dans le code C++. Par exemple, std::vector<int> tab; puis &tab[0].
    Idem pour trimbaler tes données, rien n'empêche d'avoir des références en paramètres si les valeurs nulles sont une erreur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void Tracertool::updateTracerSet(CCornerList_Int& newCornerList){
    plutôt que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void Tracertool::updateTracerSet(CCornerList_Int* newCornerList){
    if(newCornerList==NULL)
    {//erreur
    }
    calloc : soit le buffer est géré par la même classe C++ et alors préférer le new, soit le buffer est libéré par une couche C et alors le mélange allocation/libération dans des couches différentes ouvre un gros risque.

    Même en C, les pointeurs de pointeurs (de pointeurs) de void, ça devient suspect.

Discussions similaires

  1. Pointeurs et pointeurs de pointeurs
    Par wallace27 dans le forum C
    Réponses: 10
    Dernier message: 09/04/2015, 22h07
  2. Réponses: 12
    Dernier message: 06/12/2009, 10h11
  3. Réponses: 21
    Dernier message: 06/08/2009, 09h31
  4. Réponses: 6
    Dernier message: 26/05/2007, 00h33
  5. comment savoir ce que fait mon pointeur??
    Par elekis dans le forum C++
    Réponses: 9
    Dernier message: 30/11/2004, 12h42

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