Du må være registrert og logget inn for å kunne legge ut innlegg på freak.no
X
LOGG INN
... eller du kan registrere deg nå
Dette nettstedet er avhengig av annonseinntekter for å holde driften og videre utvikling igang. Vi liker ikke reklame heller, men alternativene er ikke mange. Vær snill å vurder å slå av annonseblokkering, eller å abonnere på en reklamefri utgave av nettstedet.
  8 1324
Jeg sitter nå og prøver å komme inn i C++ igjen, etter en periode med Python. Og det ser ut som jeg sliter litt med pekere og lister. Jeg vet jeg hadde litt prolemer med dette før, så prøver å bli bedre på dette.

Kildekode: http://etse001.pastebin.com

Jeg har laget en liste som jeg følte virket helt fint. Det gikk fint å legge til elementer og så hente de ut igjen. Men når jeg sletter 1 eller fler elementer oppstår det et merkelig problem. I koden min generer jeg 3 elementer som legges til i listen så sletter jeg det andre elementet. Det som da skjer er at det første elementet funerer helt fint, men når den prøver seg med det 3. elemente som får jeg opp en feilmelding over at pekeren "img" ikke fungerer.
Unhandled exception at 0x0089c586 in space battle.exe: 0xC0000005: Access violation reading location 0xabababc7.
Vis hele sitatet...
Debuggeren henviser meg da til objects.cpp fila, hvor den på linje klager på følgende:

Kode

76. sf::Sprite sprite(*img);
her ser jeg at pekeren peker på en Image klasse, men alle variabelene i klassen står med "Expression cannot be evaluated".

Hvis jeg lar være å slette noen elementer fungerer alle 3 elementene som ligger i lista. Så det å slette et element ødelegger for de andre. Sletter jeg det første elementet i listen skjer det samme igjen. Men om jeg sletter det siste elementet i listen fungerer alt tilsynelatende greit, til jeg avslutter programmet - da får jeg en "debug assertion error".
Hvor den klager på at linje 76. i list.cpp

Kode

delete curr; // delete current
Jeg blir mege taknemmelig om noen kunne se over og hjelpe meg
Kunne du lagt opp en kildekode som kun benytter seg av listen du har laget (og med feilen du kommer over), slik at jeg slipper å dra ned biblioteket du bruker?
Ukjent
Trådstarter Donor
jada takker for at du vil se på det.
http://etse002.pastebin.com - denne gjør bruker bare integere som den legger i lista. Får problemer da og.
Takker. Er en stund siden jeg har lekt med linkedlists, men jeg mener jeg fant årsaken til feilen din. Det var naturligvis i del-funksjonen din du hadde en aldri så liten feil.

Kode

// Delete element from list
void List::del()
{
	prev = curr->next; // Skips current
	delete curr; // delete current
	curr = prev; // next becomes current
	length--;
}
Feilen kommer av at det opprinnelige forrige objektet ditt enda vil peke til området til nåværende curr etter at du har slettet curr. Så når du har resatt listen din, og du går videre til next på linkede objekt, vil du ende opp (på objektet før det du slettet) med å gå til et minneområde som du ikke har allokert, og dermed ikke tilgang til. Det som du derfor må gjøre, før du setter prev = curr->next er å få den til å peke til korrekt posisjon. Altså neste fra curr.

Kode

// Delete element from list
void List::del()
{
	prev->next = curr->next;
	prev = curr->next; // Skips current
	delete curr; // delete current
	curr = prev; // next becomes current
	length--;
}
Når du arbeider med "triksing" av pekere, kan det lønne seg å tegne opp listen på et papir og gå igjennom den stegvis for å se hvordan den vil se ut mens du foretar endringene dine. Da kommer det ganske tydelig fram.
Sist endret av m0b; 8. februar 2010 kl. 06:13.
Ukjent
Trådstarter Donor
Sitat av |d13m0b Vis innlegg
Takker. Er en stund siden jeg har lekt med linkedlists, men jeg mener jeg fant årsaken til feilen din. Det var naturligvis i del-funksjonen din du hadde en aldri så liten feil.

Kode

// Delete element from list
void List::del()
{
    prev = curr->next; // Skips current
    delete curr; // delete current
    curr = prev; // next becomes current
    length--;
}
Feilen kommer av at det opprinnelige forrige objektet ditt enda vil peke til området til nåværende curr etter at du har slettet curr. Så når du har resatt listen din, og du går videre til next på linkede objekt, vil du ende opp (på objektet før det du slettet) med å gå til et minneområde som du ikke har allokert, og dermed ikke tilgang til. Det som du derfor må gjøre, før du setter prev = curr->next er å få den til å peke til korrekt posisjon. Altså neste fra curr.

Kode

// Delete element from list
void List::del()
{
    prev->next = curr->next;
    prev = curr->next; // Skips current
    delete curr; // delete current
    curr = prev; // next becomes current
    length--;
}
Når du arbeider med "triksing" av pekere, kan det lønne seg å tegne opp listen på et papir og gå igjennom den stegvis for å se hvordan den vil se ut mens du foretar endringene dine. Da kommer det ganske tydelig fram.
Vis hele sitatet...
Dette så ut til å løse problemet. Takker. Jeg hadde en følelse det var noe så enkelt som dette. Men når man er litt usikker er det lett å debugge seg blind i egen kode føler jeg. Dette fikseti hvertfall begge programmene

Takk for hjelpen.
Ja, det er kjapt å bli sittende fast i en tankerekke og ikke helt være sikker på hva det er som forårsaker uventede resultat. Derfor er jeg stor-fan av å tegne hvordan minnet og pekerne er allokert. Nå vet jeg ikke hvordan du vanligvis bruker å debugge, men Visual Studio har i alle fall noen kjempeverktøy til å gjøre skikkelig debugging. Det er veldig enkelt å sette watches på objekter og variabler så man hele tiden har kontroll over hvilken verdi de har. I tillegg kan man expande/dereference og navigere seg igjennom pekerne slik at man ser direkte hvor de peker.

Hvis du ikke er kjent med debugging i Visual Studio (om det er det du bruker) anbefaler jeg deg å gjøre deg kjent med det. Det er et paradigmeskifte hva debugging angår!
1. Hvorfor bruker du prev? Jeg så bare raskt gjennom koden, men la ikke merke til at du brukte den noen gang.
2.

Kode

void List::Next()
{
        if(curr!=NULL)
        {
                prev = curr;
                //prev->next = curr->next;
                prev->next = prev->next; //Samme funksjon som linjen over, regner med du ser hva som er rart
                curr = curr->next;
        }
}
3. Jeg mener del funksjonen din burde sett slik ut, med mindre jeg har misforstått noe

Kode

// Delete element from list
void List::del()
{
	curr = curr->next; // next becomes current
           delete prev->next; // delete current
           prev->next = curr;
	length--;
}
Sist endret av TanteSpiker; 9. februar 2010 kl. 00:33.
Ukjent
Trådstarter Donor
Akkurat nå brker jeg den som en midlertidig peker for når jeg sletter et element. Slik at den holder på det forrige elementet i listen, slik at jeg kan endre pekeren i dette elementet til å peke på neste element i listen (altså endre den så den hopper over det elementet jeg skal slette).
Selvfølgelig visste jeg det. *facepalm*
Men det jeg sa om de andre punktene gjelder fortsatt.