Avatar billede _jepsen_ Nybegynder
20. marts 2004 - 10:06 Der er 10 kommentarer og
1 løsning

Uduelig kode

Hvad i følgende kode kan sætte AntalBrugte til en ulovlig værdi?

template  <class T>
class DynArray
{

    private:
    T *Graf;
    int AntalBrugte;    //Antallet af brugte pladser, og index på næste ledige plads
    int MaxAntal;      //det antal der kan fyldes op til, uden der skal vokses
    int Iterator;      //iterator brugt ved first next more
    void Grow()
    {
        T * temp = new T[MaxAntal+=1];
        printf("Jeg vokser!\n");
        for (int i = 0; i<AntalBrugte ; i++)
            temp[i] = Graf[i];
        delete [] Graf;
        Graf = temp;
    }

    public:
    DynArray()
    {
        AntalBrugte = 0;
        MaxAntal = 10;
        Iterator = 0;
        Graf = new T[MaxAntal];
    }
    int Tilfoj(T *N)
    {
        if (AntalBrugte>=MaxAntal)
            Grow();
        Graf[AntalBrugte] = (*N);
        AntalBrugte++;
        return AntalBrugte -1; //index på sidst indsatte
    }
    void FjernSidste()
    {
        if ( AntalBrugte>0)
        {
            AntalBrugte--;
        }
        else
            throw Exception("DynArray::FjernSidste - forsøg på at fjerne fra tom liste!");

    }
    T * operator[](int Index)
    {
        if (Index < AntalBrugte)
            return &Graf[Index];
        else
            throw Exception("Der blev spurgt på et ulovligt element DynArray::operator[] Index: "+IntToStr(Index));
    }
    int GetIterator()
    {
        return Iterator;
    }
    int GetAntalBrugte()
    {
        int temp = AntalBrugte;
        return temp;
    }
    void SatIterator(int Plads)
    {
        if ((AntalBrugte <= Plads) || (AntalBrugte <0))
            throw Exception("DynArray::SatIterator, forsøg på ulovlig indstilling af iterator!");
        else
            Iterator = Plads;

    }
    void Nulstil()
    {
        delete Graf;
        Graf = new T[MaxAntal];
        AntalBrugte = 0;
        Iterator = 0;
    }
    void First()
    {
      Iterator = 0;
    }
    void Last()
    {
        Iterator = AntalBrugte -1;
    }
    void Next()
    {
        if (Iterator <= AntalBrugte)
            Iterator++;
        else
            throw Exception("DynArray::Next()  - forsøg på at iterere ud over listen - Iterator:"+IntToStr(Iterator));
    }
    void Previous()
    {
        if (Iterator-1 >= 0)
            Iterator--;
        else
            throw Exception("DynArray::Previous - forsøg på læsning af index mindre end 0");
    }
    bool More()
    {
        return (Iterator < AntalBrugte);
    }
    bool Less()
    {
        return (Iterator-1 >= 0);
    }
    T * GetLast()
    {
        if (AntalBrugte>0)
            return &Graf[AntalBrugte-1];
        else
            throw Exception("DynArray::GetLast forsøg på at læse fra tom liste!!!");

    }
    T * GetThis()
    {
        return &Graf[Iterator];
    }
    int GetIteratorValue()
    {
        return Iterator;
    }
};

koden afvikles i bcb6 hvis det har nogen betydning.
Avatar billede arne_v Ekspert
20. marts 2004 - 10:10 #1
Der er ikke noget NULL for int.

Og da den sættes til zero i constructor er det vel også fint.

Hvis du fortælle rhvad problemet er, så kan vi måske komme med et godt forslag.
Avatar billede _jepsen_ Nybegynder
20. marts 2004 - 10:12 #2
Når jeg har puttet nogle forskellige data ind i listen og bruger nogle af metoderne, så er AntalBrugte ligepludselig sat til 19568556 i en liste med 2 elementer, det giver selvfølgelig fejl når jeg itererer derud af. Og da det er en privat variabel må det være et eller andet sted i ovenstående kode den er gal...
Avatar billede arne_v Ekspert
20. marts 2004 - 10:17 #3
Ikke nødvendigvis.

En memory overskrvning kan godt ske et andet sted i koden.
Avatar billede _jepsen_ Nybegynder
20. marts 2004 - 10:20 #4
Det har du egentlig ret i... Hvordan faen debugger man sådannoget?

Ovenstående kode er en del af et større projekt.
Avatar billede arne_v Ekspert
20. marts 2004 - 10:21 #5
Hvis du har en debugger der tillader dig at sætte watch på en bestemt adresse
var det en mulighed.

Ellers skrive løbende ud hvad AntalBrugte er og se hvornår den går galt.
Avatar billede arne_v Ekspert
20. marts 2004 - 10:22 #6
Jeg håber at dine T klasser har en fornuftig = operator.
Avatar billede arne_v Ekspert
20. marts 2004 - 10:27 #7
Default = operator laver jo memcpy og når en af kopierne laver en delete
af en dynamisk allokeret member variabel så peger den andens kopi jo på
noget som systemet tror er ledigt og kan genbruges.
Avatar billede _jepsen_ Nybegynder
20. marts 2004 - 10:27 #8
Hvo, du siger noget der, jeg har da vist en enkelt klasse der bruger pointere hvor jeg ikke har forsynet den med en = operator... Det kigger jeg lige på.
Avatar billede segmose Nybegynder
20. marts 2004 - 10:46 #9
_jepsen : du kan prøve at tilføje et data break point i din klasse, run->add breakpoint.

Du mangler copy constructor og assigment operator for din class, lav den privat med en throw i sig hvis du ikke mener der er nogen der bør bruge dem.

Build all og se efter om der er nogen temporary used for xxx, så få dem løst.

Nu er jeg ikke sikker men kan dette ikke gå galt for 0 elementer?
void Last() {
  Iterator = AntalBrugte -1;
}

// her går det galt med negativt Index
T * operator[](int Index) { // måske unsigned???
  if (Index < AntalBrugte)
    return &Graf[Index];
  else
    throw Exception("Der blev spurgt på et ulovligt element DynArray::operator[] Index: "+IntToStr(Index));
}
Avatar billede _jepsen_ Nybegynder
20. marts 2004 - 11:01 #10
Arne kan du ikke ligge et svar, det var en T-klasse uden =operator, nu kører det fint!
Avatar billede arne_v Ekspert
20. marts 2004 - 11:12 #11
svar
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester