Gå til innhold

pointers: Modified after it was freed.


Anbefalte innlegg

Aldri vært spesielt stødig på pointers, så jeg spør etter litt visdom her!

 

running = true;
int nr = 0;

PrimitiveObj * prop;
while(running){

nr = getNumberOfPrimitives()-1;
for(int r = 0; r < nr; r++) {

  prop = getPrimitive(r);
 glm::vec3 pos = prop->getPos()+glm::vec3(0,1.0f,0);
 prop->setPos(pos);

}

boost::this_thread::yield();
}

delete prop;
boost::this_thread::yield();
running = false;

 

Denne kodesnutten blir styrt av en annen tråd, så loopen er ikke evig btw!

 

Feilkode: HEAP[TTTTT.exe]: HEAP: Free Heap block 20385a8 modified at 20385e0 after it was freed

 

Feilen blir trigget når "nr" er større enn ett element, bruker en pointer for å få referansen til PrimitiveObj'en som det er snakk om, istedenfor å bare få verdien.

 

Får den fra disse funksjonene:

 

int getNumberOfPrimitives(){
return prims.size();
}
PrimitiveObj * getPrimitive(int input) {
return prims[input];
}

 

Hva gjør jeg galt? :tease:

Endret av Leif.ross
Lenke til kommentar
Videoannonse
Annonse


free(prop);
prop = NULL;

Først så kaller du free på en variabel og så forsøker du å tilordne variabelen en verdi... Feilmeldingen sier at du forsøker å endre (les: tilordne en verdi til) variabelen etter at den har blitt frigitt.

 

Hva kan være galt?

 

Får feilkoden i "for-loopen", altså før den kommer til dette stadiet.

Lenke til kommentar

Kommenter alltid ut linje for linje og verifiser at retur-resultatene stemmer med det du vil frem til.

 

Lurer på om det faktisk kan være et multithreading problem istedenfor et pointer problem, får nå bare problemer med den når jeg spammer nye objekter. Kan være at de forskjellige trådene prøver å skrive til samme variabel elns. Hmm.

 

Edit: Yes, problemet er at to tråder prøver å skrive til samme variabel samtidig, må finne en vei ut av det! Skal prøve å finne ut hvordan mutex locks fungerer, men det er jo umulig å finne noe oppdatert info om det, bruker boost tråder btw!

Endret av Leif.ross
Lenke til kommentar

Er dette C eller C++ ? (Ser vel ut som C++ etter en nærmere studie).

 

Ser du har både free og delete i kodeeksempelet. De skal ikke blandes. Objekter laget med new skal slettes med delete, og free brukes på resultat fra alloc familen av funskjoner.

 

Men hvem er det som har ansvaret for å slette objektet som returneres fra getPrimitive()? din kode eller biblioteket der getPrimitive() kommer fra?

Lenke til kommentar

Yes sir! OpenGL3.3!

 


void generatePrimitive(){
PrimitiveObj * obj = new PrimitiveObj();
obj->generate();
obj->setPos(getPlayerPos()+getEye()*4.0f);
prims.push_back(obj);
}

 

Usikker på om det er denne snutten som feller meg nå, har en følelse av at jeg bare kopierer den samme pointeren hver gang denne funksjonen blir kjørt.

 

Feilkoden er nå:

First-chance exception at 0x0133ed89 in TTTTT.exe: 0xC0000005: Access violation reading location 0xfeeefefe.

Unhandled exception at 0x772215de in TTTTT.exe: 0xC0000005: Access violation reading location 0xfeeefefe.

Endret av Leif.ross
Lenke til kommentar

Hvorfor gjør du free på det i det hele tatt? Etter koden å dømme, så er dette en peker som denne funksjonen ikke burde ha noen som helst kontroll over.

 

Koden er modifisert nå, og bruker ikke free! :p Problemet ser ut til å ligge i den siste funksjonen jeg postet.

Lenke til kommentar

free(prop);
prop = NULL;

 

Først så kaller du free på en variabel og så forsøker du å tilordne variabelen en verdi... Feilmeldingen sier at du forsøker å endre (les: tilordne en verdi til) variabelen etter at den har blitt frigitt.

 

Isolert sett er det ingenting galt med disse to linjene. Man kan gjerne sette en peker til noe (være det et nytt objekt eller NULL) etter å ha frigjort det objektet som pekeren pekte på opprinnelig.

Lenke til kommentar

Aller først -- kan du poste det minste komplette eksempelet som illustrerer problemet?

 

Aldri vært spesielt stødig på pointers, så jeg spør etter litt visdom her!

 

running = true;
int nr = 0;

PrimitiveObj * prop = NULL;
while(running) {
   nr = getNumberOfPrimitives();
   for(int r = 0; r < nr; r++) {
    prop = getPrimitive(r);
    glm::vec3 pos = prop->getPos()+glm::vec3(0,1.0f,0);
    prop->setPos(pos);
   } 
}

if(prop!=NULL) {
  free(prop);
  prop = NULL;
}

running = false;
//delete prop;

 

Denne kodesnutten blir styrt av en annen tråd, så loopen er ikke evig btw!

 

Aha, begynte å lure på akkurat det.

 

Flere har påpekt på free()-vs-delete, og du skal definitivt ikke blande de to sammen. Du nevner også threading -- kan feilen skyldes at objektene blir manipulert fra flere tråder og derfor har man en tråd som aksesserer et objekt som er blitt slettet i en annen tråd?

 

(...) bruker en pointer for å få referansen til PrimitiveObj'en som det er snakk om, istedenfor å bare få verdien.

 

Jeg sliter med å forstå hvordan dette utsagnet gir mening.

 

Får den fra disse funksjonene:

int getNumberOfPrimitives(){
return prims.size();
}
PrimitiveObj * getPrimitive(int input) {
return &prims[input];
}

 

Er prims global? Hvis ja, hvordan blir tilgangen til den synkronisert fra flere tråder? Du bruker push_back(), men husk på at hvert kall på push_back() kan potensielt forårsake en reallokering i den underliggende vektoren, som vil gjøre samtlige av de adressene du har fått gjennom getPrimitive() ugyldige.

Lenke til kommentar

Isolert sett er det ingenting galt med disse to linjene. Man kan gjerne sette en peker til noe (være det et nytt objekt eller NULL) etter å ha frigjort det objektet som pekeren pekte på opprinnelig.

Faktisk så kan det være en god ide å sette pekeren til NULL, både fordi free ikke gjør det, og fordi det kan være lettere å fange opp feil da.

Lenke til kommentar

Aller først -- kan du poste det minste komplette eksempelet som illustrerer problemet?

 

 

 

Aha, begynte å lure på akkurat det.

 

Flere har påpekt på free()-vs-delete, og du skal definitivt ikke blande de to sammen. Du nevner også threading -- kan feilen skyldes at objektene blir manipulert fra flere tråder og derfor har man en tråd som aksesserer et objekt som er blitt slettet i en annen tråd?

 

 

 

Jeg sliter med å forstå hvordan dette utsagnet gir mening.

 

 

 

Er prims global? Hvis ja, hvordan blir tilgangen til den synkronisert fra flere tråder? Du bruker push_back(), men husk på at hvert kall på push_back() kan potensielt forårsake en reallokering i den underliggende vektoren, som vil gjøre samtlige av de adressene du har fått gjennom getPrimitive() ugyldige.

 

 

Ideen var å lagre alle pointerene i en vektor, slik at jeg senere kan bruke denne vektoren for å få tilgang til alle pointerene, som igjen gir tilgang til objektene.

 

Jeg har en rendering tråd som bare skal lese fra objektene, og rendre på bakgrunn av den informasjonen, og en fysikk tråd, som bare leser og oppdaterer informasjonen for hvert objekt.

 

Trådene er ikke helt synkroniserte, men jeg bruker mutex locks for å hindre at to tråder prøver å kommme innpå samme variabel samtidig.

Lenke til kommentar

Gjelder dette selv om jeg legger til pekerne i vektoren, og ikke selve objektet?

 

Din getPrimitive() returnerer adressen til et element i vectoren. Dette betyr at når du tar en push_back() (dvs. kaller generatePrimitive()), vil ikke nødvendigvis adressen være gyldig lenger.

 

Du kan legge til shared_ptr/vanlig peker heller enn objektene selv i vectoren, men hvorvidt det gir mening er det vanskelig å si uten å kjenne til programmet.

Lenke til kommentar

Oppdatert med ny kode i OP! Fortsatt feil?

 

Bedre, men (som nevnt alt), bør du redusere dette til det minste komplette eksempelet. Får du den samme feilen fremdeles?

 

(dette er litt på siden av det opprinnelige problemet, men (siden du først bruker boost), hvorfor gidder du å syssle med manuell deallokering? boost::shared_ptr gjør at du slipper å tenke på delete. Det å faktisk unngå å kalle delete eksplisitt er et nokså prisverdig mål i seg selv i C++).

Endret av zotbar1234
Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
×
×
  • Opprett ny...