I'm trying to write a function that pushes an item onto the end of my dynamically allocated array (not allowed to use vectors). Once it goes to the area to double the size of the list if the list was too small to store the next number, it all goes to hell and starts feeding me back random numbers from the computer. Can anyone see why it's not doubling like it's suuposed to?
int *contents_;
int *temp;
int size_ = 0;
int capacity_ = 1;
void pushBack(int item) /**appends the specified value to DynArray; if the contents array is full,
double the size of the contents array and then append the value **/
{
if (size_ == capacity_)
{
capacity_ = (2*capacity_);
temp = new int[capacity_];
for (int i = 0; i < size_; ++i)
{
temp[i] = contents_[i];
}
delete [] contents_;
contents_ = temp;
}
contents_[size_++] = item;
}
EDIT ** I forgot to mention. This is a function out of a class. This is in the header and in main :
main()
{
DynArray myArray;
myArray.pushBack(2);
myArray.pushBack(3);
myArray.printArray();
return 0;
}
If this is your initial setup:
int *contents_; // Junk
int size_ = 0;
int capacity_ = 1;
Then your code is most likely performing a memory access violation upon the first time it does:
if (size_ == capacity_)
{
// Not entering here, contents_ remains junk
}
contents_[size_++] = item;
As barak implied, the contents_ pointer needs to be initialized. If not, c++ will point it to something you probably don't want it to.
Related
My instructions are...
// Description: Places the payload contents of the list in the
// array referenced by 'populateMeWithElements'.
// Returns the number of elements that were placed
// in the provided memory location.
// Precondition: Enough memory has been allocated to the provided
// memory location to hold the full contents
// of the list.
// Postcondition: The memory allocated for 'populateMeWithElements'
// has been deallocated after the completion of
// this method call.
int getListElements(int* populateMeWithElements);
I have this written...
int OOLList::getListElements(int* populateMeWithElements) {
int count = 0;
OOLNode* iterator = this->start;
int* populateMeWithElements = new int[getListSize()];
for (int i = 0; iterator->next != NULL; i++) {
populateMeWithElements[i] = iterator->payload;
iterator = iterator->next;
count++;
}
return count;
}
but I am not sure if it is correct and if it is...
How do I display the contents in my driver
Where I deallocate the memory (do I do this in the driver or in the function that I wrote?)
Thanks in advance for any suggestions or help.
Your function is declaring a local populateMeWithElements variable that shadows the input populateMeWithElements parameter. You are filling the array that you allocate locally, you are not populating the caller's array at all.
For that matter, your function should not be using new[] at all, since the instructions clearly state that the precondition of the function is that the caller has already allocated an array of sufficient size beforehand, and will deallocate that array after the function exits. So, your function's job is merely to fill the caller's array, nothing more.
And on that task, your loop is wrong. iterator->next != NULL needs to be iterator != NULL, otherwise if the list is empty then the 1st access of iterator->next will fail, and if the list is not empty then the payload of the tail node will be skipped.
Try this instead:
int OOLList::getListElements(int* populateMeWithElements) {
int count = 0;
OOLNode* iterator = this->start;
for (int i = 0; iterator != NULL; i++) {
populateMeWithElements[i] = iterator->payload;
iterator = iterator->next;
++count;
}
return count;
}
OOLList list;
// populate list as needed...
int* elements = new int[list.getListSize()];
int count = list.getListElements(elements);
for(int i = 0; i < count; ++i) {
// use elements[i] as needed...
}
delete[] elements;
The function can be simplified a bit further:
int OOLList::getListElements(int* populateMeWithElements) {
int count = 0;
for (OOLNode* iterator = this->start; iterator != NULL; iterator = iterator->next) {
populateMeWithElements[count++] = iterator->payload;
}
return count;
}
Or even:
int OOLList::getListElements(int* populateMeWithElements) {
int* ptr = populateMeWithElements;
for (OOLNode* iterator = this->start; iterator != NULL; iterator = iterator->next) {
*ptr++ = iterator->payload;
}
return ptr - populateMeWithElements;
}
I am working on an assignment that involves me writing a template class for a queue. It uses a dynamically allocated array. I am having trouble with the copying of the array. This is the prompt.
aQueue.setCapacity(newCapacity), that changes the capacity of aQueue to newCapacity. (This is much trickier than Stack::setCapacity(): if newCapacity is zero or < getSize(), setCapacity() should throw an exception; otherwise, it should allocate a new array with the new capacity, copy the values from the old array into the new array, and deallocate the old array.) To help you see all the things that can go wrong, you should make certain your method passes all the tests in this test method before working on the rest of the project.
Instance variables are:
unsigned mySize; // number of items I contain
unsigned myCapacity; // how many items I can store
unsigned myFirst; // index of oldest item (if any)
unsigned myLast; // index of next available spot for append (if any)
Item* myArray; // dynamic array of items
This is what I have so far:
template <class Item>
void ArrayQueue<Item>::setCapacity(unsigned newCapacity) {
if (newCapacity == 0 || newCapacity < mySize) {
throw QueueException("setCapacity()","newCapacity is too small");
} else {
Item * newArray = new Item[newCapacity];
unsigned y = myFirst;
for (unsigned x = 0; x < mySize; x++) {
newArray[y] = myArray[x];
y++;
}
delete [] myArray;
myArray = newArray;
myCapacity = newCapacity;
myLast = y;
}
}
These are the methods for getFirst() and getLast():
// Method returns first Item in ArrayQueue
template <class Item>
unsigned ArrayQueue<Item>::getFirst() const {
if (this->isEmpty()) {
throw EmptyQueueException("getFirst()");
} else {
return myArray[myFirst];
}
}
// Method returns last Item in ArrayQueue
template <class Item>
unsigned ArrayQueue<Item>::getLast() const {
if (this->isEmpty()) {
throw EmptyQueueException("getLast()");
} else {
return myArray[(myLast - 1 + myCapacity) % myCapacity];
}
}
I have been working on this for hours so any help would be greatly appreciated.
Credit goes to: Aconcagua
for (unsigned x = 0; x < mySize; x++) {
newArray[x] = myArray[(y % myCapacity)];
y++;
}
delete [] myArray;
myArray = newArray;
myCapacity = newCapacity;
myFirst = 0;
myLast = mySize;
By setting myFirst to 0 and myLast to mySize this properly allocates the indexes correctly. In addition to this when copying the array you most set newArray[x] to myArray[(y % myCapacity)].
I want to resize the array when the rehash function is called, by copying the values of initial dictionary into it and then at last redifining the newdictionary as dictionary
void rehash ()
{
int newsize=2*Size;
node **newdictionary;
newdictionary= new node*[newsize];
//Initialising the dictionary
for (int i = 0;i < newsize;i++)
{
newdictionary[i]->name = "";
newdictionary[i]->value = -1;
}
node **temp=dictionary;
delete [] dictionary;
dictionary=newdictionary;
SIZE=newsize;
for(int i=0;i<SIZE;i++)
{
if(temp[i]->value!= -1)
insertvalue(temp[i]->name,temp[i]->value);
}
delete [] temp;
};
Earlier I have defined insertvalue as:
void insertvalue (string filedata, int code)
{
// tableindex is the position where I want to insert the value
dictionary[tableindex]->name= filedata;
dictionary[tableindex]->value=code;
};
You didn't actually explain what problem(s) you're having, but your code has several issues:
void rehash ()
{
int newsize=2*Size;
node **newdictionary;
newdictionary= new node*[newsize];
At this point, newdictionary is simply an array of uninitialized pointers.
//Initialising the dictionary
for (int i = 0;i < newsize;i++)
{
newdictionary[i]->name = "";
newdictionary[i]->value = -1;
}
So the loop above is trying to access the members of node objects that don't yet exist.
node **temp=dictionary;
delete [] dictionary;
These two lines don't make sense. dictionary and temp point to the same memory. So when you delete dictinoary you've deleted the memory that temp is pointing to.
dictionary=newdictionary;
SIZE=newsize;
for(int i=0;i<SIZE;i++)
{
if(temp[i]->value!= -1)
insertvalue(temp[i]->name,temp[i]->value);
}
Even if you hadn't just deleted the memory out from under temp, you're now trying to access temp from 0 to the new size, not the old size. In other words, this would access temp beyond its bounds.
Those are the major problems that I've noticed in the code so far. You at least need to correct all of them before there's any hope of this working. You probably need to spend some time really stepping through your logic to ensure it makes sense in the end.
Here's my code:
template<class T> class Test
{
public:
int Size = 0;
int Length = 0;
T* Items;
Test() {}
~Test()
{
delete [] Items;
}
void Append(const T& newItem)
{
if (Size + 1 >= Length)
{
Length += 250;
T* old = Items;
Items = new T[Length + 250];
for (int i = 0; i < Size; i++)
Items[i] = old[i];
delete [] old;
}
Items[Size] = newItem;
Size++;
}
};
Test<int> test;
for (int i = 0; i < 500000; i++)
test.Append(i);
I'm populating the dynamic array with 500000 integers which must take just 1-2Mb but it takes about 30Mb. There's no problem if i set the initial size to 500000(i.e. no resizing occurring). The grow value(250) seems to affect the memory somehow, if it's larger(for example 1000) then the memory usage is pretty low. What's wrong?
Typically, when you are reallocating an array, you do not want to modify the actual array until the very last second (to maintain exception safety):
T* temp = new T[new_size];
// assume count is the previous size and count < new_size
std::copy(Items, Items + count, temp);
std::swap(temp, Items);
delete [] temp;
Aside from that, there is nothing visible in your code that would cause a memory leak.
The extra size can possibly be due to other optimizations (being turned off) and/or debugging symbols being turned on. What compiler options are you using (and what compiler)? It should be noted that extra size is not necessarily an indication of a memory leak. Have you run this in a debugger or memory profiler which found a leak?
It should also be noted that std::vector does all of this for you.
Looking at your code, you're going to segfault more so than leak memory due to the fact that calling delete or delete[] on a non-NULL, but previously deallocated, pointer is a Bad Thing. Also, I don't believe this is your real code, because what you posted won't compile.
When you delete a pointer, always set it to NULL afterwards. It's good practice to initialize to NULL as well. Let's fix up your code to make sure we don't call delete on previously deallocated pointers. Also, let's initialize our pointer to NULL.
Your misuse of memory probably stems from the following lines of code:
Length += 250;
T* old = Items;
Items = new T[Length + 250];
Notice that you increment Length by 250, but then allocate Length+250 more elements? Let's fix that, too.
template<class T>
class Test
{
public:
int Size;
int Length;
T* Items;
Test() : Size(0), Length(0), Items(NULL){}
~Test() {
if (Items != NULL)
delete [] Items;
}
void Append(const T& newItem)
{
if (Size + 1 >= Length)
{
Length += 250;
T* old = Items;
Items = new T[Length];
for (int i = 0; i < Size; i++)
Items[i] = old[i];
delete [] old;
old = NULL;
}
Items[Size] = newItem;
Size++;
}
};
int main(){
Test<int> test;
for (int i = 0; i < 500000; i++)
test.Append(i);
}
I am trying to insert an int into an array that is in a class object, and I cannot figure out what I am doing wrong. The current state of my code never inserts the int into the array.
Basically what I am trying to do is when i call insert(int) it will check to to see if there is any room left in the array, and if there is it will add it, otherwise it would reallocate with 8 more spaces in the array.
here is some relevant class info
private:
unsigned Cap; // Current capacity of the set
unsigned Num; // Current count of items in the set
int * Pool; // Pointer to array holding the items
public:
// Return information about the set
//
bool is_empty() const { return Num == 0; }
unsigned size() const { return Num; }
unsigned capacity() const { return Cap; }
// Initialize the set to empty
//
Set()
{
Cap = Num = 0;
Pool = NULL;
}
here is the code i am working on
bool Set::insert(int X)
{
bool Flag = false;
if (Num == Cap)
{
//reallocate
const unsigned Inc = 8;
int * Temp = new int[Cap+Inc];
for (unsigned J=0;J<Num;J++)
{
Temp[J] = Pool[J];
}
delete [] Pool;
Pool = Temp;
Cap = Cap+Inc;
}
if(Num < Cap)
{
Pool[Num+1] = X;
Flag = true;
}
return Flag;
}
Your insert function never updates Num. Try Pool[Num++] = X; or something like that.
You probably want to increment the number of element but only after copying the new element in: the first element should have index 0. Basically, your insert() function should look something like this:
bool Set::insert(int X)
{
if (Num == Cap)
{
const unsigned Inc(std::max(8, 2 * Cap));
std::unique_ptr<int[]> Temp(new int[Cap+Inc]);
std::copy(Pool.get(), Pool.get() + Num, Temp.get());
Pool.swap(Temp);
Cap += Inc;
}
Pool[Num] = X;
++Num;
return true;
}
Of course, this assumes that Pool is reasonably declared as std::unique_ptr<int[]> (or something with similar functionality which is easy to write if necessary). The reason to use std::unique_ptr<int[]> rather than raw pointers is that they automatically clean up resources when they are destroyed. Copying a sequence of ints won't throw an exception but if int get's replaced by a std::string or a template parameters there is potential to throw exceptions.