2013-03-27 7 views
7

Wprowadzam podwójnie połączoną listę typów sortów, która przechowuje "wiadra" (węzły), z których każda zawiera predefiniowaną liczbę znaków. Każde wiadro przechowuje wskaźnik do następnego i poprzedniego segmentu, a klasa listy (BucketString) przechowuje wskaźnik do nagłówka Bucket. Mam kompilacji za pomocą g ++, który zgłasza błądC++: zakończenie wywoływane po rzuceniu instancji 'std :: bad_alloc'

terminate called after throwing an instance of 'std::bad_alloc' 
    what(): std::bad_alloc 
make: *** [run] Aborted (core dumped) 

ilekroć uruchomić kod i dodać ciąg znaków do listy, używając następującej dodać metodę, która jest zawarta w mojej klasie wiadro, i nazywa się od wymieniaj własne metody klasy w razie potrzeby.

Kod:

std::size_t bucketSizeB; 
int filled; 
char* str; 
Bucket* next; 
Bucket* prev; 

Bucket::Bucket() : bucketSizeB(7), str(new char[7]), next(NULL), prev(NULL), filled(0) 
{} 

Bucket::Bucket(std::size_t bucketSizeB_) : bucketSizeB(bucketSizeB_), str(new char[bucketSizeB]), next(NULL), prev (NULL), filled(0) 
{} 

Bucket::Bucket(const Bucket& rhs) : bucketSizeB(rhs.bucketSizeB), next(rhs.next), prev(rhs.prev), filled(rhs.filled) 
{ 
    for (int i = 0 ; i < (int) bucketSizeB ; i++) 
    { 
     str[i] = rhs.str[i]; 
    } 
} 

void Bucket::add(std::string line) 
{ 

    int diff = bucketSizeB - filled; //if the bucket is already partially filled 


    std::string tmp = line.substr(0, diff); 

    for (std::size_t i = 0 ; i < tmp.length() ; i++) 
    { 

     str[filled] = line[i]; 
     ++filled; 
    } 

    if (line.length() > bucketSizeB) 
    { 

     next = new Bucket(bucketSizeB); 

     next->prev = this; 
     next->add(line.substr(diff, line.length()-diff)); 
    } 
} 
Bucket::~Bucket() 
{ 
    if (prev) 
    { 
     if (next) 
     { 
      prev->next = next; 
     } 
     else 
     { 
      prev->next = NULL; 
     } 
    } 
    if (next) 
    { 
     if (prev) 
     { 
      next->prev = prev; 
     } 
     else 
     { 
      next->prev = NULL; 
     } 
    } 
    delete [] Bucket::str; 
} 

Gdy zostanie zgłoszony błąd, metoda add jest wywoływana z „listy” członek klasy metody append, która działa w następujący sposób:

void BucketString::append (std::string& line) 
{ 
    length += line.length(); //Just a way to store the length of the string stored in this BucketString object 

    if (!head) //If the head node pointer is currently null, create a new head pointer 
    { 

     head = new Bucket(bucketSize); 
    } 

    Bucket* tmp = head; 

    while (tmp->next) //Finds the tail node 
    { 
     tmp = tmp->next; 
    } 
    tmp->add(line); //Calls the Bucket add function on the tail node 
} 

pliku nagłówka dla klasy kubełków jest:

#include <cstddef> 
#include <string> 
#include <iostream> 

#ifndef BUCKET_H_ 
#define BUCKET_H_ 

namespace RBNWES001 
{ 
class Bucket 
{ 

    public: 
     //Special members and overloaded constructor 
     Bucket(void); 
     Bucket(std::size_t); 
     Bucket(const Bucket&); 
     ~Bucket(); 
     //Copy Assignment not included because it's not needed, I'm the only one who is gonna use this code! :) 

     //Add method 
     void add(std::string); 

     int filled; 
     char* str; 
     Bucket* next; 
     Bucket* prev; 
     std::size_t bucketSizeB; 
}; 
} 

#endif 
+1

Witaj w SO, ale pozwól, że zapytam: co próbujesz? Czy dodałeś instrukcje drukowania, aby zobaczyć, skąd pochodzi błąd? Czy użyłeś debuggera? (I nie, kod, który pokazałeś, nie wystarcza) –

+0

Dodałem wspomniane instrukcje drukowania, w ten sposób wiem, że są zgłaszane, gdy ta metoda jest wywoływana. Dziwne jest to, że metoda wydaje się działać poprawnie dla pierwszych 70 lub więcej znaków dodanych, ale wtedy wiadomość jest wyrzucana. Co jeszcze chcesz? Niestety, klasa 'list' jest dość długa, uwzględnię tę metodę w klasie 'list' (zwanej BucketString), która wywołuje tę metodę, jeśli to trochę pomaga. – wesrobin

+0

bad_alloc jest zgłaszane przez operatora new, gdy brakuje pamięci. Ponieważ add używa rekursji, być może rekursje wymykają się z pamięci. – engineerC

Odpowiedz

5

to działa: w moim Bucket(std::size_t bucketSizeB) konstruktora inicjator dla str powinien zmienić się z str(new char[bucketSizeB] na str(new char[bucketSizeB_]) (tj. użyć argumentu przekazanego do cos ntructor zamiast użycia zmiennej bucketSizeB).

+0

Ponieważ elementy są inicjowane w kolejności, w jakiej zostały zadeklarowane. Powinieneś otrzymać ostrzeżenie, jeśli twoje ustawienia kompilatora są wystarczająco wysokie. – GManNickG

+1

@GManNickG, Nie widzę powodu, dla którego otrzymasz ostrzeżenie o konkretnym błędzie. Zmienna "bucketSizeB' została wcześniej zdefiniowana jako globalna ... –

5

1) Możesz zapobiec zakończeniu z blokiem try/catch.

2) Wygląda na to, że dzieje się tak podczas uruchamiania programu. To również brzmi jak "make" automatycznie uruchamia program. Poprawny?

3) Jeśli tak, chcesz zaglądać do debuggera i określić dokładną linię, na której się zawiesił.

4) Podejrzewam, że jeśli prześledzisz kod, zobaczysz, że co najmniej jeden z elementów "diff", "bucketSizeB" i/lub "wypełniony" staje się bardzo duży (lub ujemny). Który byłby błędem :) Które można łatwo naprawić - gdy go znajdziesz.

5) Tutaj są dobre tutoriale na GDB, jeśli tak się stanie, aby być wygodne debugger dla Ciebie:

http://dirac.org/linux/gdb/

http://www.cs.cmu.edu/~gilpin/tutorial/

http://www.cprogramming.com/gdbtutorial.html

+0

1) ukrywa błąd i pogarsza sprawę, nie rozwiąże problemu. 2) jest nieistotny. 3) powinien być (już jest) komentarzem. –