3 Replies - 1493 Views - Last Post: 10 September 2011 - 03:10 PM Rate Topic: -----

#1 andre1011  Icon User is offline

  • D.I.C Head

Reputation: 1
  • View blog
  • Posts: 87
  • Joined: 12-January 11

Data Structures, run time error, Debug error: invalid allocation

Posted 09 September 2011 - 12:24 PM

Hello my name is Andre and keep getting this run time error, Debug error: invalid allocation size 429 ... bytes
I am using Visual Studio 2008 on a Windows XP SP3 machine

The driver for my class sequence has a function called "show_sequence" with this definition

void show_sequence(sequence display)
// Library facilities used: iostream
{
for (display.start( ); display.is_item( ); display.advance( ))
cout << display.current( ) << endl;
}

When a sequence is first created it is empty so "display.is_item( )" must return false and "display.advance( )" will not increment the class variable "current_index", so you can not advance to the next number in the sequence, so this for loop can not print anything. This is the behavior I expect.

But I keep getting the run time error, "Debug error: invalid allocation size 429 ... bytes" when I call the "show_sequence" function. I need to know why this is happening. Here is my code

First the header file: sequence.h
// FILE: sequence1.h
// CLASS PROVIDED: sequence (part of the namespace CISP430_A2)
// There is no implementation file provided for this class since it is
// an exercise from Section 3.2 of "Data Structures and Other Objects Using C++"
//
// TYPEDEFS and MEMBER CONSTANTS for the sequence class:
//   typedef ____ value_type
//     sequence::value_type is the data type of the items in the sequence. It
//     may be any of the C++ built-in types (int, char, etc.), or a class with a
//     default constructor, an assignment operator, and a copy constructor.
//
//   typedef ____ size_type
//     sequence::size_type is the data type of any variable that keeps track of
//     how many items are in a sequence.
//
//   enum { CAPACITY = 30 };
//     CAPACITY is the maximum number of items that a sequence can hold.
//
// CONSTRUCTOR for the sequence class:
//   sequence(size_type entry=CAPACITY );
//     Postcondition: The sequence has been dynamic allocate memories.
//
//COPY CONSTRUCTOR
//   sequence(const sequence& entry)
//   Postcondition: The sequence has been created by copying from an existing sequence.
//
// MODIFICATION MEMBER FUNCTIONS for the sequence class:
//   void start( )
//     Postcondition: The first item on the sequence becomes the current item
//     (but if the sequence is empty, then there is no current item).
//
//   void advance( )
//     Precondition: is_item returns true.
//     Postcondition: If the current item was already the last item in the
//     sequence, then there is no longer any current item. Otherwise, the new
//     current item is the item immediately after the original current item.
//
//   void insert(const value_type& entry)
//     Precondition: size( ) < CAPACITY. if this is not true then increase the capacity by 10%
//     Postcondition: A new copy of entry has been inserted in the sequence
//     before the current item. If there was no current item, then the new entry 
//     has been inserted at the front of the sequence. In either case, the newly
//     inserted item is now the current item of the sequence.
//
//   void attach(const value_type& entry)
//     Precondition: size( ) < CAPACITY.if this is not true then increase the capacity by 10%
//     Postcondition: A new copy of entry has been inserted in the sequence after
//     the current item. If there was no current item, then the new entry has 
//     been attached to the end of the sequence. In either case, the newly
//     inserted item is now the current item of the sequence.
//
//   void remove_current( )
//     Precondition: is_item returns true.
//     Postcondition: The current item has been removed from the sequence, and the
//     item after this (if there is one) is now the new current item.
//
//Operator= overloading
//   void sequence::operator =(const sequence&);
//     Postcondition:  The l-value's sequence object is copy to the r-value
//
// CONSTANT MEMBER FUNCTIONS for the sequence class:
//   size_type size( ) const
//     Postcondition: The return value is the number of items in the sequence.
//
//   bool is_item( ) const
//     Postcondition: A true return value indicates that there is a valid
//     "current" item that may be retrieved by activating the current
//     member function (listed below). A false return value indicates that
//     there is no valid current item.
//
//   value_type current( ) const
//     Precondition: is_item( ) returns true.
//     Postcondition: The item returned is the current item in the sequence.
// Destructor
//	 ~sequence()  
//     Postcondition: release the memory to the heap
//
// VALUE SEMANTICS for the sequence class:
//    Assignments and the copy constructor may be used with sequence objects.
//
//void resize(size_type new_capacity )
//Precondition: new_capacity > used
// Postcondition: new space allocated and old space released
//
//bool isnotanumber(double x)
//precondition: variables "x" and "y" must be initialized in the calling function is_item
//postcondition: returns true if "x" is NOT >= 0 AND "x" is NOT <= 0  all else false
//


#ifndef SEQUENCE_H
#define SEQUENCE_H
#include <cstdlib>  // Provides size_t

namespace CISP430_A2
{
    class sequence
    {
    public:
        // TYPEDEFS and MEMBER CONSTANTS
        typedef double value_type;
        typedef size_t size_type;
        enum { CAPACITY = 30 };
        // CONSTRUCTOR
        sequence(size_type entry=CAPACITY );
		   // COPY CONSTRUCTOR
        sequence(const sequence& entry);       
    // Library facilities used: cstdlib
        // MODIFICATION MEMBER FUNCTIONS
        void start( );
        void advance( );
        void insert(const value_type& entry);
        void attach(const value_type& entry);
        void remove_current( );
		void resize(size_type );
		void sequence::operator =(const sequence&);
        // CONSTANT MEMBER FUNCTIONS
        size_type size( ) const;
        bool is_item( ) const;
        value_type current( ) const;
		//Destructor
		 ~sequence()  ;
    private:
        value_type *data;
        size_type used;
		size_type capacity;   /* The current capacity of the data array it is initialy set to CAPACITY  */
        mutable size_type current_index;    /* made mutable because the const current() function 
                                               must change current_index if is_item returns false */
		bool isnotanumber(double x) const;
		
    };
}

#endif


Now the class implementation: sequence.cpp
#include <math.h>       /* supplies isnan() */
#include "sequence.h"

namespace CISP430_A2
{
	/* Parameterizied Default Constructor */
	sequence::sequence(size_type entry)
	{
      data = new value_type[entry];             //dynamically allocate memory space for 30 elements
      used = 0;                                // initial amount of elements inside the array (empty array) 
      current_index = 0;                      //initially the current index should be the first position in the array

	}/* end default parameterizied constructor */ 

	/* Copy Constructor */
	sequence::sequence(const sequence& entry)
	{
      data = new value_type[entry.capacity]; /* copy constructor ensures that the new object will have its own 
	                                            dynamically allocated memory */
	  used = entry.used;
      current_index = entry.current_index;

	}/* end of copy constructor */

	/* Destructor */
    sequence::~sequence()
	{
      delete [] data;                       //free memory for array data
	}/* end of destructor */

	/* If the sequence is not empty sets the current index to zero, otherwise it does nothing */
void sequence::start()
	{
      if(used > 0)
	  {
        current_index = 0;
	  }
	}/* end of start function */

/* is x a number? */
bool sequence::isnotanumber(double x) const
{
   if( !(x >= 0 ) && !(x <= 0) )
   {
      return true;
   }
   return false;
}/* end of isnotanumber function */

/* Test if there is a number at the current index of the array */
bool sequence::is_item() const
{
 double x = 100;
 double y = 0;
 double placeHolder;

 x/=y;                     /* isnotanumber() will not work without these two lines */
 x/=x;                     /* both lines make "x" = NaN */

 placeHolder = data[current_index]; /* get the contents of the current position of the data array 
                                       and store in placeHolder */
/* If isnotanumber() returns true then is_item() returns false so current() returns Null */
/* If isnotanumber() returns false then is_item() returns true so current() returns the number inside data[] */
 if( (isnotanumber(placeHolder)) || ( used==0 ) || ( used >= capacity ) || ( current_index > used ) ) 
 {                               
   return false;
 }
 else
 {
   return true;
 }

}/* end of is_item function */


/* will return the current number in the sequence if is_item returns true  */
sequence::value_type sequence::current() const
{
  if( ( is_item() ) && ( used > 0 ) )
  {
    return data[current_index];
  }
  else
  {
     current_index = used;
     return NULL;
  }
}/* end of current function */

/* advances the current index by 1 */
void sequence::advance()
{
	if( current_index < (used - 1) )
	{
      current_index++;
	}
  
}/* end of advance function */

/* returns the number of items in the sequence */
sequence::size_type sequence::size() const
{
  return used;
}/* end of size function */
 
}/* end of namespace CISP430_A2 */



Finally the driver: sequence_test.cpp
// FILE: sequence_test.cpp
// An interactive test program for the new sequence class
#include <cctype>       // Provides toupper
#include <iostream>     // Provides cout and cin
#include <cstdlib>      // Provides EXIT_SUCCESS
#include "sequence.h"  // With value_type defined as double
using namespace std;
using namespace CISP430_A2;

// PROTOTYPES for functions used by this test program:
void print_menu( );
// Postcondition: A menu of choices for this program has been written to cout.

char get_user_command( );
// Postcondition: The user has been prompted to enter a one character command.
// The next character has been read (skipping blanks and newline characters), 
// and this character has been returned.

void show_sequence(sequence display);
// Postcondition: The items on display have been printed to cout (one per line).

double get_number( );
// Postcondition: The user has been prompted to enter a real number. The
// number has been read, echoed to the screen, and returned by the function.


int main( )
{
    sequence test; // A sequence that well perform tests on
    char choice;   // A command character entered by the user
    
    cout << "I have initialized an empty sequence of real numbers." << endl;
 
    do
    {
        print_menu( );
        choice = toupper(get_user_command( )); 
        switch (choice)
        {
            case '!': test.start( );
                      break; 
            case '+': test.advance( );
                      break;
            case '?': if (test.is_item( ))
                          cout << "There is an item." << endl;
                      else 
                          cout << "There is no current item." << endl;
                      break;
            case 'C': if (test.is_item( ))
                           cout << "Current item is: " << test.current( ) << endl;
                      else
                          cout << "There is no current item." << endl;
                      break;
            case 'P': show_sequence(test);
                      break;
            case 'S': cout << "Size is " << test.size( ) << '.' << endl;
                      break;/*
            case 'I': test.insert(get_number( ));
                      break;
            case 'A': test.attach(get_number( ));
                      break;
            case 'R': test.remove_current( );
                      cout << "The current item has been removed." << endl;
                      break;     
            case 'Q': cout << "Ridicule is the best test of truth." << endl;
                      break; */
            default:  cout << choice << " is invalid." << endl;
        }
    }
    while ((choice != 'Q'));

    return EXIT_SUCCESS;
}

void print_menu( )
// Library facilities used: iostream.h
{
    cout << endl; // Print blank line before the menu
    cout << "The following choices are available: " << endl;
    cout << " !   Activate the start( ) function" << endl;
    cout << " +   Activate the advance( ) function" << endl;
    cout << " ?   Print the result from the is_item( ) function" << endl;
    cout << " C   Print the result from the current( ) function" << endl;
    cout << " P   Print a copy of the entire sequence" << endl;
    cout << " S   Print the result from the size( ) function" << endl;
    cout << " I   Insert a new number with the insert(...) function" << endl;
    cout << " A   Attach a new number with the attach(...) function" << endl;
    cout << " R   Activate the remove_current( ) function" << endl;
    cout << " Q   Quit this test program" << endl;
}

char get_user_command( )
// Library facilities used: iostream
{
    char command;

    cout << "Enter choice: ";
    cin >> command; // Input of characters skips blanks and newline character

    return command;
}

void show_sequence(sequence display)
// Library facilities used: iostream
{
    for (display.start( ); display.is_item( ); display.advance( ))    /* I believe this is the problem */
        cout << display.current( ) << endl;
}
/*
double get_number( )
// Library facilities used: iostream
{
    double result;
    
    cout << "Please enter a real number for the sequence: ";
    cin  >> result;
    cout << result << " has been read." << endl;
    return result;
} */




any help will be appreciated THANK YOU

Is This A Good Question/Topic? 0
  • +

Replies To: Data Structures, run time error, Debug error: invalid allocation

#2 Salem_c  Icon User is offline

  • void main'ers are DOOMED
  • member icon

Reputation: 1629
  • View blog
  • Posts: 3,092
  • Joined: 30-May 10

Re: Data Structures, run time error, Debug error: invalid allocation

Posted 09 September 2011 - 01:14 PM

015	    /* Copy Constructor */
016	    sequence::sequence(const sequence& entry)
017	    {
018

A couple of things spring to mind.
1. You don't guard against self-assignment.
2. You only allocate a new array, you don't copy all the contents.

Perhaps you could also make show_sequence() take a reference parameter rather than a value parameter.
Was This Post Helpful? 1
  • +
  • -

#3 Hezekiah  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 207
  • View blog
  • Posts: 550
  • Joined: 12-July 09

Re: Data Structures, run time error, Debug error: invalid allocation

Posted 09 September 2011 - 10:55 PM

data = new value_type[entry.capacity];

You never initialize capacity, but then use it to allocate memory.
//in first constructor
capacity = entry;

//in copy constructor
capacity = entry.capacity;

Was This Post Helpful? 0
  • +
  • -

#4 andre1011  Icon User is offline

  • D.I.C Head

Reputation: 1
  • View blog
  • Posts: 87
  • Joined: 12-January 11

Re: Data Structures, run time error, Debug error: invalid allocation

Posted 10 September 2011 - 03:10 PM

Hello Hezekiah I tried what you said and it worked, here is my updated copy constructor

void sequence::operator =(const sequence& source)
{
value_type *new_data;

if(this == &source) /* check for self alignment */
{
return;
}

if(capacity != source.capacity)
{
new_data = new value_type[source.capacity];
delete [] data;
data = new_data;
capacity = source.capacity;
}

used = source.used;
copy(source.data, source.data + used, data);

}/* end of overloaded assignment operator = */
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1