wesrobin
wesrobin

Reputation: 390

C++: terminate called after throwing an instance of 'std::bad_alloc'

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

Upvotes: 9

Views: 56845

Answers (2)

wesrobin
wesrobin

Reputation: 390

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).

Upvotes: 5

paulsm4
paulsm4

Reputation: 121789

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

Upvotes: 5

Related Questions