I am implementing a doubly linked list class of sorts which stores 'buckets' (the nodes), which each contain a predefined number of characters. Each bucket stores a pointer to the next and previous bucket, and the list class (BucketString) stores a pointer to the head Bucket. I am compiling using g++ which throws the error
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
make: *** [run] Aborted (core dumped)
whenever I run the code and add a string of characters to the list, using the following add method, which is contained within my bucket class, and is called from the list class's own methods whenever needed.
Code:
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;
}
When the error is thrown, the add method is being called from the 'list' class member method append, which works as follows:
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
}
The header file for the bucket class is:
#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) You can prevent termination with a try/catch block.
2) It sounds like this is occurring when you execute the program. It also sounds like "make" executes the program automatically. Correct?
3) If so, you want to look in a debugger and identify the exact line where it's crashing.
4) I suspect if you trace through the code you'll see that one or more of "diff", "bucketSizeB" and/or "filled" become very large (or negative). Which would be a bug :) Which you can easily fix - once you find it.
5) Here's are good tutorials on GDB, if that happens to be a convenient debugger for you:
http://dirac.org/linux/gdb/
http://www.cs.cmu.edu/~gilpin/tutorial/
http://www.cprogramming.com/gdbtutorial.html
This works: in my Bucket(std::size_t bucketSizeB)
constructor the initialiser for str
should change from str(new char[bucketSizeB]
to str(new char[bucketSizeB_])
(ie. use the argument passed to the cosntructor instead of using the bucketSizeB variable).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With