25. august 2003 - 19:30Der er
12 kommentarer og 1 løsning
Kædet liste - problem med new
Jeg har implementeret en kædet liste i C++. Jeg har stort set fået det til at virke, men: Hvis jeg først fylder en liste, tømmer den, og dernæst forsøger at fylde data i den igen - så får jeg en unhandled exception i _heap_alloc_base funktionen i filen malloc.c, når jeg forsøger at oprette et nyt dataelement med new.
Helt præcist får jeg meddelelsen: Unhandled exception at 0x77f75a58 in lab1.exe: User breakpoint
Og i debug vinduet står følgende: HEAP[lab1.exe]: HEAP: Free Heap block 370f08 modified at 370fd8 after it was freed Unhandled exception at 0x77f75a58 in lab1.exe: User breakpoint.
Det skal siges, at jeg ikke har pillet ved definitionen af new eller andet. Jeg bruger MS VC++ 7.
Jeg forstår ikke helt hvad der er galt - specielt fordi det hele fungerer fint første gang der fyldes data i listen. Er der nogen der kan hjælpe ?
De fejl du nævner skyldes sansynligvis at du i har en fejl i din kode, fejlen kan f.ex. være at du: 1: Skriver ud over enden af en buffer 2: Skriver til en buffer efter at du har frigivet den 3: Frigiver den samme buffer flere gange 4: Forsøger at frigive en buffer som du ikke har allokeret
Vis os noget kode, så kan det være at vi kan hjælpe
// indsæt data template <class T> void ListBuffer<T>::put(T value) { ListNode<T> * ny = new ListNode<T> ; ListNode<T> * tmp = 0 ;
if ( !ny ) exit(1) ;
ny->putData(value) ; ny->setNext(0) ;
tmp = last ; last = ny ; if ( tmp != 0 ) tmp->setNext(ny) ;
if ( first == 0 ) first = last ; }
// Hent data template <class T> T ListBuffer<T>::get() { if ( !isEmpty() ) { T d = first->getData() ; ListNode<T> * n = first ; first = first->getNext() ; delete n ; return d ; }else { return 0 ; // vi skal returnere noget. } }
// er ListBuffer tom ? template <class T> bool ListBuffer<T>::isEmpty() { return ( first == 0 ? true : false ) ; }
// tæl antal elementer template <class T> int ListBuffer<T>::count() { int i = 0 ; ListNode<T> * c = first ;
if ( isEmpty() ) return 0 ; else { i++ ; while ( c->getNext() != 0 ) { i++ ; c = c->getNext() ; } return i ; } } // ---------- fil slut
Buffer er en abstrakt basisklasse, som danner grundlag for grænsefladen til ListBuffer. ListNode er en hjælpe klasse, den indeholder data og en pointer til næste element, som det også fremgår:
template <class T> class ListNode { public: ListNode() ; // default constructor ListNode(T inData, ListNode<T> * nnext = 0);// constructor T getData() ; bool putData(T nyData) ; ListNode<T> * getNext() ; void setNext(ListNode<T> * nnext) ; private: T data ; ListNode<T> * next ; };
arne_v >> Det var lige nøjagtig dét der var galt ( og jeg kan selv se problemet i det nu ). Skriv et svar, du har fortjent dine point.
Jeg har lige et sidespørgsmål : Grænsefladen i ListBuffer skal svare til den i basisklassen Buffer - og denne indeholder funktionen isFull, som skal returnere om bufferen er fuld. Hvordan kan jeg hensigtsmæssigt implementere isFull() på ListBuffer ? ListBuffer er jo først fuld, når der ikke er mere hukommelse til rådighed. Er der en metode, hvorpå man kan spørge allokeringssystemet om der er plads til rådighed til et enkelt element ?
Man kunne vel implementere det således: // er ListBuffer fuld ? template <class T> bool ListBuffer<T>::isFull() { ListNode<T> * tmp = new ListNode<T> ; if ( !tmp ) return true ; else { delete tmp ; return false ; } }
... men jeg synes det er lidt voldsomt først at allokere plads og så slette det igen, blot for at finde ud af om der er plads til et element mere eller ej.
du kan returnere false hver gang i isFull. Det er i hvert fald tilnærmelsesvis rigtigt. Venter du til der ikke er mere virtuelt lager tilbage vil din applikation alligevel køre så langsomt, så det kan være ligemeget.
Nej - som du nok kan se i eksemplet går jeg ud fra at new returnerer 0 hvis den ikke er i stand til at allokere hukommelse. Er det compiler eller library specifikt om den returnerer 0 eller smider en exception ? Eller kommer det an på noget andet.
Men jeg tror jeg følger erikjacobsen's råd med at returnere false hver gang - som i selv siger, burde det ikke være et problem.
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.