无效读取的4个valgrind大小

问题描述 投票:0回答:1

我使用valgrind运行我的代码,并收到“无效读取的4号大小”错误。这正是我得到的:

==15103==    at 0x10F74C: NoeudHydro<noeud*>::GetNumero() const (NoeudHydro.h:97)
==15103==    by 0x10ECE1: std::ostream& operator<< <noeud*>(std::ostream&, NoeudHydro<noeud*>) (NoeudHydro.h:191)
==15103==    by 0x10E15A: main (main.cpp:71)
==15103==  Address 0x5b88450 is 0 bytes inside a block of size 240 free'd
==15103==    at 0x4C3123B: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==15103==    by 0x110943: __gnu_cxx::new_allocator<NoeudHydro<noeud*> >::deallocate(NoeudHydro<noeud*>*, unsigned long) (new_allocator.h:125)
==15103==    by 0x1105C1: std::allocator_traits<std::allocator<NoeudHydro<noeud*> > >::deallocate(std::allocator<NoeudHydro<noeud*> >&, NoeudHydro<noeud*>*, unsigned long) (alloc_traits.h:462)
==15103==    by 0x10FBE7: std::_Vector_base<NoeudHydro<noeud*>, std::allocator<NoeudHydro<noeud*> > >::_M_deallocate(NoeudHydro<noeud*>*, unsigned long) (stl_vector.h:180)
==15103==    by 0x112102: void std::vector<NoeudHydro<noeud*>, std::allocator<NoeudHydro<noeud*> > >::_M_realloc_insert<NoeudHydro<noeud*> >(__gnu_cxx::__normal_iterator<NoeudHydro<noeud*>*, std::vector<NoeudHydro<noeud*>, std::allocator<NoeudHydro<noeud*> > > >, NoeudHydro<noeud*>&&) (vector.tcc:448)
==15103==    by 0x111E47: void std::vector<NoeudHydro<noeud*>, std::allocator<NoeudHydro<noeud*> > >::emplace_back<NoeudHydro<noeud*> >(NoeudHydro<noeud*>&&) (vector.tcc:105)
==15103==    by 0x111CCF: std::vector<NoeudHydro<noeud*>, std::allocator<NoeudHydro<noeud*> > >::push_back(NoeudHydro<noeud*>&&) (stl_vector.h:954)
==15103==    by 0x111AE6: AjoutNoeudHydro(std::vector<NoeudHydro<noeud*>, std::allocator<NoeudHydro<noeud*> > >&, noeud*, char, int, int*) (passerelleRT.cpp:48)
==15103==    by 0x1119EC: ParcoursAxe(axe*, std::vector<NoeudHydro<noeud*>, std::allocator<NoeudHydro<noeud*> > >&, int*, int) (passerelleRT.cpp:36)
==15103==    by 0x10E0E1: main (main.cpp:68)
==15103==  Block was alloc'd at
==15103==    at 0x4C3017F: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==15103==    by 0x1109D3: __gnu_cxx::new_allocator<NoeudHydro<noeud*> >::allocate(unsigned long, void const*) (new_allocator.h:111)
==15103==    by 0x110680: std::allocator_traits<std::allocator<NoeudHydro<noeud*> > >::allocate(std::allocator<NoeudHydro<noeud*> >&, unsigned long) (alloc_traits.h:436)
==15103==    by 0x10FE55: std::_Vector_base<NoeudHydro<noeud*>, std::allocator<NoeudHydro<noeud*> > >::_M_allocate(unsigned long) (stl_vector.h:172)
==15103==    by 0x111FC5: void std::vector<NoeudHydro<noeud*>, std::allocator<NoeudHydro<noeud*> > >::_M_realloc_insert<NoeudHydro<noeud*> >(__gnu_cxx::__normal_iterator<NoeudHydro<noeud*>*, std::vector<NoeudHydro<noeud*>, std::allocator<NoeudHydro<noeud*> > > >, NoeudHydro<noeud*>&&) (vector.tcc:406)
==15103==    by 0x111E47: void std::vector<NoeudHydro<noeud*>, std::allocator<NoeudHydro<noeud*> > >::emplace_back<NoeudHydro<noeud*> >(NoeudHydro<noeud*>&&) (vector.tcc:105)
==15103==    by 0x111CCF: std::vector<NoeudHydro<noeud*>, std::allocator<NoeudHydro<noeud*> > >::push_back(NoeudHydro<noeud*>&&) (stl_vector.h:954)
==15103==    by 0x111AE6: AjoutNoeudHydro(std::vector<NoeudHydro<noeud*>, std::allocator<NoeudHydro<noeud*> > >&, noeud*, char, int, int*) (passerelleRT.cpp:48)
==15103==    by 0x1119EC: ParcoursAxe(axe*, std::vector<NoeudHydro<noeud*>, std::allocator<NoeudHydro<noeud*> > >&, int*, int) (passerelleRT.cpp:36)
==15103==    by 0x10E0E1: main (main.cpp:68)

这是我的代码:

#include <iostream>
#include "NoeudHydro.h"
#include "passerelleRT.h"
using namespace std;

bool EstNoeudReit(PTNoeud Nd){
    PTNoeud Ndsuivant=Nd->suiv;
    return SontConfondus(Nd,Ndsuivant);
}

bool SontConfondus(PTNoeud Nd1, PTNoeud Nd2){
    return Nd1->pos[0]==Nd2->pos[0] && Nd1->pos[1]==Nd2->pos[1] && Nd1->pos[2]==Nd2->pos[2];
}

void ParcoursAxe(PTAxe AxeCourant,vector< NoeudHydro<PTNoeud> >& SysHydro, int TabEqui[],int temps){
    PTNoeud NdSRCourant=AxeCourant->premNoeud;
    NdSRCourant=NdSRCourant->NdDistSurAxeFils;

    while(NdSRCourant!=NULL){
        if(NdSRCourant->NdDistSurAxeFils!=NULL){ //Si c'est un Nd Ramif/Reit
            if(EstNoeudReit(NdSRCourant)){
                AjoutNoeudHydro(SysHydro,NdSRCourant,'2',temps,TabEqui);
                PTNoeud NdTemp=NdSRCourant->suiv;
                while(SontConfondus(NdTemp,NdSRCourant)){
                    TabEqui[NdTemp->num]=SysHydro.size()-1; //le numero du NoeudHydro venant d etre ajoute
                                                           //est la taille du vecteur -1
                    SysHydro[SysHydro.size()+1].SetEquivalentSysRac(NdTemp);
                    NdTemp=NdTemp->suiv;
                }
            }//end if EstNoeudReit

            else{ //C est un Nd Ramif
                AjoutNoeudHydro(SysHydro,NdSRCourant,'1',temps,TabEqui);
            }

        }//end if Nd Ramif/Reit

        else{
            AjoutNoeudHydro(SysHydro,NdSRCourant,'0',temps,TabEqui);
        }
        NdSRCourant=NdSRCourant->suiv;
    }
}

void AjoutNoeudHydro(vector< NoeudHydro<PTNoeud> >& SysHydro,PTNoeud NdSR, char typeNd, int temps,int TabEqui[]){

    //Ajout dans le vecteur
    SysHydro.push_back(NoeudHydro<PTNoeud> (NdSR,SysHydro.size(),typeNd,temps));
    //Relation Pere-Fils
    SysHydro.back().SetPere(SysHydro[TabEqui[NdSR->prec->num]]);
    SysHydro[TabEqui[NdSR->prec->num]].SetFils(SysHydro.back()); 

    //Equivalences
    TabEqui[NdSR->num]=SysHydro.size()-1;
}



int main(){

    int tempsTotal=28;

    /*-----------------------------------------------------*/
    /*SOME CODE THAT DOES WORK AND NEEDED FOR THE NEXT PART*/
    /*-----------------------------------------------------*/


    cout<<"------------------------------------------"<<endl;
    cout<<"-------------------HYDRO------------------"<<endl;
    cout<<"------------------------------------------"<<endl;

    // //HYDRO
    NoeudHydro<PTNoeud> *Nd;
    Nd=new NoeudHydro<PTNoeud> (SRG.GetSR()->premAxe->suivant->premNoeud,0,'0',tempsTotal);

    vector< NoeudHydro<PTNoeud> > SysHydro;
    int TabEqui[27]; 
    TabEqui[0]=-9;
    TabEqui[4]=0;
    SysHydro.push_back(*Nd);

    ParcoursAxe(SRG.GetSR()->premAxe->suivant,SysHydro,TabEqui,tempsTotal);

    for(int i=0;i<SysHydro.size();i++){
        cout<<SysHydro[i]<<endl;
        cout<<endl;
    }
    delete Nd;
    return 0;  
} 

以及有问题的班级:

#ifndef NOEUDHYDRO
#define NOEUDHYDRO

#include <iostream>
#include <vector>

#include "fonctions_Info_Element.h"

using namespace std;

template <typename T>
class NoeudHydro{

    private :
        int numero; //numero dans l hydro
        int typeRacine;
        int ordreRamif;
        char typeNd; //(noeud simple =0, ramif = 1, reit = 2)
        float coordonnes[3]; //coordonnees
        double diametre;
        int age;
        float distanceApex;

        double conductAxiale; //conductance axiale entre le pere et lui meme
        double conductRadiale;

        NoeudHydro<T>* Pere;
        vector<NoeudHydro*> Fils; //NoeudHydro suivant. Le premier est le suivant sur la meme racine. 
                                  //Les autres sont les NoeudHydro suivant sur les axes fils (s il y a)
        vector<T> EquivalentSysRac; //Liste des Noeud/Seg du SysRac equivalents

    public : 
        //CONSTRUCTEURS/DESTRUCTEUR
        NoeudHydro(); //par defaut
        NoeudHydro(T& Element,int num, char typeNd,  int temps);
        ~NoeudHydro();

        //ACCESSEURS
        int GetNumero() const;
        NoeudHydro<T>* GetPere() const;
        NoeudHydro<T>* GetFils(int i) const; 
        T GetEquivalentSysRac(int i) const;
        int GetNbEquivalentSysRac() const;

        void SetNumero(int i);
        void SetPere(NoeudHydro<T>& Pere);
        void SetFils(NoeudHydro<T>& Fils);

};

template <typename T>
NoeudHydro<T>::NoeudHydro(T& Element,int num, char typeNd, int temps){
    this->Pere=NULL;

    this->numero=num;
    this->typeRacine=TypeRacineElement(Element);
    this->ordreRamif=OrdreRamifElement(Element);
    this->typeNd=typeNd;

    for(int i=0;i<3;i++){
        this->coordonnes[i]=CoordonneesElement(Element,i);
    }

    this->diametre=DiametreElement(Element);
    this->age=AgeElement(Element,temps);
    this->EquivalentSysRac.push_back(Element);
    cout<<"NoeudHydro "<<this->numero<<" cree"<<endl;
}

template <typename T>
NoeudHydro<T>::~NoeudHydro(){    cout<<"NoeudHydro "<<this->numero<<" detruit"<<endl;
}



//ACCESSEURS

template <typename T>
int NoeudHydro<T>::GetNumero() const{
    return this->numero;
}

template <typename T>
NoeudHydro<T>* NoeudHydro<T>::GetPere() const{
    return this->Pere;
}

template <typename T>
NoeudHydro<T>* NoeudHydro<T>::GetFils(int i) const{
    return this->Fils[i];
}

template <typename T>
void NoeudHydro<T>::SetNumero(int i){
    this->numero=i;
}

template <typename T>
void NoeudHydro<T>::SetPere(NoeudHydro& NdPere){
    this->Pere=&NdPere;
}

template <typename T>
void NoeudHydro<T>::SetFils(NoeudHydro& NdFils){
    this->Fils.push_back(&NdFils);
}


//Operateur
template <typename T>
ostream& operator<<(ostream& stream, NoeudHydro<T> Nd){
    if(Nd.GetPere()!=NULL){cout<<"Noeud Pere : "<<Nd.GetPere()->GetNumero()<<endl;} 
    for(int i=0;i<Nd.GetNbFils();i++){
        cout<<"Fils numero "<<i<<" : noeud "<<Nd.GetFils(i)->GetNumero()<<endl;
    } 
    return stream;
}
#endif

错误似乎来自GetNumero(),但如果执行此操作则没有错误

NoeudHydro<PTNoeud> Nd(parameter needed);
Nd.GetNumero();

仅当我执行Nd.GetPere()->GetNumero();

并且不明白为什么,我也注意到该代码确实起作用。 (如果我不使用valgrind,我将继续执行代码)。有人有话要说吗?

NB:PTNoeud与noeud相同*

c++ valgrind
1个回答
0
投票
很难准确地指出错误是什么,而又不能轻易地将错误追查到行号。

并且不明白为什么,我也注意到该代码确实起作用。 (如果我不使用valgrind,我将继续执行代码)。有人有话要说吗?

这是未定义行为(UB)的本质。如果UB意味着应用程序总是崩溃且运行良好且易于调试,则将非常有用。实际上,UB意味着几乎任何事情都可能发生。它可能会连续数年无副作用地运行,然后突然崩溃。

回到问题所在。 Valgrind告诉您您正在访问已删除的内容。它还告诉您这一切都发生在emplace_back中。这可能意味着vector正在调整大小,并且在调整大小时出了点问题。

我的猜测是您的问题出在您的父/子原始指针上。调整vector大小时,可能会使这些指针无效。如果这是正确的,那么您将需要修改赋值运算符/复制构造器/移动构造函数,或者只是考虑使用智能指针。

© www.soinside.com 2019 - 2024. All rights reserved.