Hey I am rehashing through a few old projects in a class I took and as I'm redoing this project I keep getting this error when my clear() function is called in the driver,
Heap Corruption Detected: after Normal block (#142)
CRT detected that the application wrote to memory after the end of the HEAP buffer
Here is my custom Vector class
#include "MyVector.h"
//insert header files
#include <iostream>
#include <string>
//setup access to necessary libraries
using namespace std;
MyVector::MyVector()
{
// initialize member data
size = 0;
capacity = 2;
//initialize new array
classArray = new int[capacity];
}
MyVector::MyVector(int maxCapacity)
{
// initialize member data
size = 0;
capacity = maxCapacity;
// initialize new array
classArray = new int[capacity];
}
MyVector::~MyVector()
{
if (classArray != NULL)
{
delete [] classArray;
classArray = NULL;
}
}
int MyVector::getSize()
{
return size;
}
int MyVector::getCapacity()
{
return capacity;
}
void MyVector::clear()
{
// delete the array
delete[] classArray;
// reinitialize the array
capacity = 2;
size = 0;
classArray = new int[capacity];
}
void MyVector::push_back(int n)
{
if (size > capacity)
{
// setup the special case of an array with 0 elements
if (size == 0)
{
clear();
}
else
{
// declare a temporary pointer and allocate a new array
capacity = capacity * 2;
int* tempArray = new int[capacity];
// copy the values from the old array to the temporary array
for (int i = 0; i < size; i++)
{
tempArray[i] = classArray[i];
}
// call the destructor
delete[] classArray;
// assign the classArray pointer to the new array
classArray = tempArray;
}
}
// pushback a new value to the array
classArray[size] = n;
// increment size
size++;
}
int MyVector::at(int n)
{
// check if n is within the bounds of the array
if (n >= size)
{
throw n;
}
// if not return the value of the index requested
else
{
return classArray[n];
}
}
and here is my driver code,
//insert header files
#include <iostream>
#include <string>
#include "MyVector.h"
//setup access to necessary libraries
using namespace std;
//declare constants
#pragma region Constants
const int TEST_VALUE1 = 21;
const int TEST_VALUE2 = 31;
const int TEST_VALUE3 = 41;
const int MAX = 12;
#pragma endregion
int main()
{
// Create a default vector
MyVector sam;
// push some data into sam
cout << "\nPushing three values into sam";
sam.push_back(TEST_VALUE1);
sam.push_back(TEST_VALUE2);
sam.push_back(TEST_VALUE3);
cout << "\nThe values in sam are: ";
// test for out of bounds condition here
// and test exception
for (int i = 0; i < sam.getSize() + 1; i++)
{
try
{
cout << sam.at(i) << " ";
}
catch (int badIndex)
{
cout << "\nOut of bounds at index " << badIndex << endl;
}
}
cout << "\n--------------\n";
// clear sam and display its size and capacity
sam.clear(); //********ERROR BEING THROWN HERE*********
cout << "\nsam has been cleared.";
cout << "\nSam's size is now " << sam.getSize();
cout << "\nSam's capacity is now " << sam.getCapacity() << endl;
cout << "---------------\n";
// Push 12 values into the vector - it should grow
cout << "\nPush 12 values into sam.";
for (int i = 0; i < MAX; i++)
sam.push_back(i);
cout << "\nSam's size is now " << sam.getSize();
cout << "\nSam's capcacity is now " << sam.getCapacity() << endl;
cout << "---------------\n";
cout << "\nTest to see if contents are correct...";
// display the values in the vector
for (int i = 0; i < sam.getSize(); i++)
{
cout << sam.at(i) << " ";
}
cout << "\n--------------\n";
cout << "\n\nTest Complete...";
cout << endl;
system("PAUSE");
return 0;
}
I've looked back and forth at my old project several times and I can't see why I am getting this error when I am trying to delete something. I mean it sounds like that usually happens when I am trying to allocate something that can't be allocated but not deleted?
Any help appreciated thanks!
Your push_back code can be reduced to:
if (size > capacity)
{
// resize
}
classArray[size] = n;
size++;
But note that you start with size == 0 and capacity == 2, then have three calls to push_back. On the third one, size == 2 and capacity == 2. size > capacity is still false, so you'll write into classArray[2] (without having resized) which is uninitialized memory. This is undefined behavior.
You want to check size >= capacity to resize.
Note that there's another serious problem with your class: you failed to write a copy constructor, so if you copied it, both copies would attempt to deallocate the same memory. See Rule of Three (updated in C++11 to Rule of Five).
Related
I need help passing an array to a function by reference. The array is created beforehand being passed to the function but the value of the array after being passed through the function is not what I want - it remains unchanged. The code is shown below. The function is to take an array, a position p and a value val. The array is assumed to be sorted in ascending order up to position p and the value val must be placed such that the array is sorted in ascending order up to position p+1.
#include <iostream>
using namespace std;
// Function that takes an array a, a position,
// and a float value val to insert.
// a must already be sorted in acsending order
// up to p. val is then inserted such that
// the a is sorted up to p+1.
// p = 0 means position a[0].
void insert(double (&a)[], int aSize, int p, double val)
{
try {
// Throw error if p > size of array
if(p > aSize || p < 0) {
throw logic_error("Position is greater than size of array or less than zero.");
}
int newSize = aSize + 1;
double* vTemp = new double[newSize]; // create new bigger array
for(int i = 0; i <= p; i++) {
if(val >= a[i]) {
vTemp[i] = a[i];
} else {
vTemp[i] = val;
for(int j = i + 1; j < newSize; j++) {
vTemp[j] = a[j - 1];
}
break;
}
}
cout << "Size of vTemp = " << newSize << endl;
for (int k = 0; k < newSize; k++){
cout << "vTemp[" << k << "] = " << vTemp[k] << endl;
}
a = vTemp;
delete[] vTemp;
} catch(const logic_error& e) {
cout << "Error in input: " << e.what() << endl;
}
}
int main()
{
// Declare variables
double myArray[] = { 1, 2, 4, 8, 16, 20, 50, 30, 153 }; // sample array to test function
int p = 5; // position
double val = 7.2; // value to insert
int arraySize = sizeof(myArray) / sizeof(myArray[0]); // no. of elements in array
int newSize = 0; // size of expanded matrix
// Insert val
insert(myArray, arraySize, p, val);
cout << "Size of original array: " << arraySize << endl;
// Display new expanded matrix
newSize = sizeof(myArray) / sizeof(myArray[0]); // size of expanded matrix
cout << "Size of expanded array: " << newSize << endl << endl;
for(int i = 0; i < newSize; i++) {
cout << myArray[i] << " ";
}
cout << endl;
// Return success
return 0;
}
Don't use raw arrays. The class you are looking for is called std::vector (reference).
Just create a vector instead of an array and pass it by reference and you get what you need.
The problem doessn't come from the array being passed by reference.
The issues is assigning a dynamic array to a built-in array.
In the case above, when the following statement is executed.
a = vTemp;
The "array , which by that point is a pointer reference" will change is value to point to the dynamic array.
But don't forget that you are deleting the array.
delete[] vTemp;
you are not actually copying each element that the dynamic allocated array have into your array. when execution goes back to main, it points to your normal array.
I am new to c++ and learning how to declare, use and delete a two dimensional array of std::string.
Because this is a learning exercise I am ignoring the idea of using vectors (for now).
I wrote a program that creates a small two dimensional array, adds data and then deletes the 2d array trying to use best practices along the way.
Can someone suggest improvements? I am most concerned about cleaning up the 2d array after I'm done using it, so I can avoid the possibility of a memory leak.
Thanks in advance.
#include <iostream>
#include <string>
using namespace std;
void DIM(std::string **marray,unsigned int row,unsigned long cols)
{
if (marray[row] != nullptr) {
delete [] marray[row];
marray[row] = nullptr;
}
marray[row] = new std::string[cols];
}
void DIM_DELETE (std::string **marray,unsigned int row)
{
if (*&marray[row] != nullptr) {
delete[] marray[row];
marray[row] = nullptr;
}
}
void DIM_DELETE_ALL (std::string **marray,unsigned int rows)
{
for (int i=(rows-1); i>-1; i--) {
if (marray[i] != nullptr) {
delete[] marray[i];
marray[i] = nullptr;
}
}//next i
//now take care of marray
if (marray != nullptr) {
delete [] marray;
marray = nullptr;
}
}
std::string **create2darray(unsigned int rows,unsigned int cols)
{
//first create the pointer
std::string **my = nullptr; //create pointer , note: no data portion assigned yet
//now assign a data portion to the pointer (could do above in one step)
my = new std::string*[rows];// elements 0 through rows-1 //assigns data section (an array of std::strings)
//now set newly created rows to nullptr
for (unsigned int i = 0; i<rows; i++) {
my[i] = nullptr;
}
//dim each row for cols columns
for (unsigned int i = 0; i<rows; i++) {
DIM(my,i,cols);//dims the strings (creates data portion) my = new std::string*[x];//
}
return my;//returning a std::string **
}
int main()
{
unsigned int rows = 3;//3 rows (0 through 2)
unsigned int cols = 4;//4 columns (0 through 3)
std::string **myarray = create2darray(rows,cols);//2d array (3 rows, 5 cols)
cout << "2d array created" << endl << endl;
myarray[0][0] = "a0"; //row 0, col 0
myarray[1][0] = "b0"; //row 1, col 0
myarray[2][0] = "c0";
myarray[0][1] = "a1";
myarray[0][2] = "a2";
myarray[0][3] = "a3";
myarray[1][1] = "b1";
myarray[1][2] = "b2";
myarray[1][3] = "b3";
myarray[2][1] = "c1";
myarray[2][2] = "c2";
myarray[2][3] = "c3";
cout << "assigned data to rows 0 to 2 and cols 0 to 3" << endl << endl;
for (unsigned int i=0; i<rows; i++) {
cout << i << ",0: " << myarray[i][0] << " " << i << ",1: " << myarray[i][1] << " " << i << ",2: " << myarray[i][2] << " " << i << ",3: " << myarray[i][3] << endl;
}
cout << endl;
cout << "we are done with 2d array, let's delete it" << endl;
//tested dim_delete (seems to work)
/*
DIM_DELETE(myarray,0);//delete [] myarray[0]; myarray[0] = nullptr;
DIM_DELETE(myarray,1);
DIM_DELETE(myarray,2);
//still need to delete myarray
delete [] myarray;
myarray = nullptr;
*/
//delete all rows and delete the std::string that holds the rows
DIM_DELETE_ALL(myarray,rows);
cout << "array deleted, all done" << endl;
//hold cursor so user can see console messages
do {} while(cin.get()!='\n');
return 0;
}
If the second dimension of your array is constant, I think you can be fine using a single new and delete operators. Something like this:
#include <stdio.h>
#include <string>
int ROWS = 3;
const int COLS = 4;
typedef std::string arr4[COLS];
int main()
{
arr4 *a;
a = new arr4[ROWS];
for (int i = 0; i < ROWS; i++)
for (int j = 0; j < COLS; j++)
a[i][j] = std::to_string(j*ROWS + i);
for (int i = 0; i < ROWS; i++)
{
for (int j = 0; j < COLS; j++)
printf("%s ", a[i][j].c_str());
printf("\n");
}
printf("\n");
delete [] a;
}
In my code, I am having trouble on my copy assignment operator. When I try to execute "=" operator in my main(), the content of my source array (numArr) is not copied to my destenation array (numArr2).
Then, for my doubleCap() function, I am try to create a bigger array of double size once my original array is full. However, if I insert delete[] newArr, the compiler will output some random numbers in my array.
This is my code in .cpp
#include <iostream>
#include "NumList.h"
using namespace std;
//Default Constructor
NumList::NumList()
{
//Actual elements stored in the array
size = 0;
//Max capacity of the array
capacity = 1;
numList = new int[capacity];
}
//Destructor
NumList::~NumList()
{
delete[] numList;
}
//Copy Constructor
NumList::NumList(const NumList& anotherNumList)
{
capacity = anotherNumList.capacity;
size = anotherNumList.size;
numList = new int[capacity];
for (int i = 0; i < size; ++i)
{
numList[i] = anotherNumList.numList[i];
}
}
//Copy Assignment Operator
NumList& NumList::operator= (const NumList& anotherNumList)
{
//Check if it is self-assigning
if (this == &anotherNumList)
return *this;
//Get rid of the old data
delete[] numList;
this->capacity = anotherNumList.capacity;
//Create and copy to the new array
numList = new int[capacity];
for (int i = 0; i < anotherNumList.size; ++i)
{
numList[i] = anotherNumList.numList[i];
}
return *this;
}
void NumList::print()
{
for (int i = 0; i < size; ++i)
{
cout << numList[i] << " ";
}
cout << endl;
}
void NumList::doubleCap()
{
capacity = capacity * 2;
//Create a new array when the capacity is full
int * newArr = new int[capacity];
for (int i = 0; i < size; ++i)
{
newArr[i] = numList[i];
}
//Let numlist points to the new array
numList = newArr;
//delete[] newArr; <--
}
void NumList::insertEnd(int val)
{
//Double the capacity of the list
if (size == capacity)
{
doubleCap();
}
numList[size] = val;
++size;
}
void NumList::insertAt(int val, int index)
{
if (index < 0 || index > capacity)
{
cout << "The index is out of range." << endl;
}
else
{
//Double the capacity of the list
if (size == capacity)
{
doubleCap();
}
for (int i = (size-1); i >= index; i--)
{
numList[i + 1] = numList[i];
}
numList[index] = val;
++size;
}
}
This is my code in main
#include <iostream>
#include <string>
#include <algorithm>
#include "NumList.h"
using namespace std;
int main()
{
NumList numArr;
NumList numArr2;
numArr.insertEnd(10);
cout << "List 1 after inserting 10: ";
numArr.print();
numArr2 = numArr;
NumList numArr3(numArr);
numArr.insertEnd(11);
numArr.insertEnd(12);
numArr.insertAt(5, 0);
cout << "List 1: ";
numArr.print();
cout << "\nPrint the list 2 of int: ";
numArr2.print();
cout << "\nPrint the list 3 of int: ";
numArr3.print();
system("pause");
return 0;
}
Output without line "delete[] newArr;",
List 1 after inserting 10: 10
List 1: 5 10 11 12
Print the list 2 of int:
Print the list 2 of int: 10
Press any key to continue . . .
Output with line "delete[] newArr;",
List 1 after inserting 10: 10
List 1: 5 -572662307 -572662307 12
Print the list 2 of int:
Print the list 2 of int: 10
Press any key to continue . . .
You are trying to delete the wrong thing. In doubleCap() you have 2 arrays, the member and the new on you create that has more space. The one that has more space is the one you want to keep so you can't delete it. What you need to do is delete the original array and then assign to it the new one. That makes the function look like
void NumList::doubleCap()
{
capacity = capacity * 2;
//Create a new array when the capacity is full
int * newArr = new int[capacity];
for (int i = 0; i < size; ++i)
{
newArr[i] = numList[i];
}
delete [] numList; // get rid of the old array
//Let numlist points to the new array
numList = newArr;
}
You are also missing the assignment of anotherNumList.size to this->size in your operator =. That causes the copied list to have the wrong size after assignment.
I have two arrays in a class, both with different sizes. My goal is to copy the second array (nArray) to the the first array (_theArray) using pointers. Below I have included the code of the function in the class, as well as the function in main to test the swap.
I have written the code below, where I try to point the first array to the second array using pointer p (int * p).
void easyArray::resize(unsigned int newSize)
{
// created new dynamic array
int * nArray = new int[newSize];
// init the new array
for (int i = 0; i < newSize; i++) {
nArray[i] = 0;
cout << nArray[i] << " ";
}
if (newSize >= _size) {
for (int i = 0; i < _size; i++) {
nArray[i] = _theArray[i];
}
} else {
cout << "not enough room" << endl;
}
destroy(); //deletes old array
int *p = _theArray; //points old to new array (?)
p = nArray; //sets old array = to new array (?)
}
in main:
void testResize()
{
easyArray a(5);
for(int i = 0; i < a.size(); i++) {
a[i] = i + 100;
}
a.resize(10);
a[9] = 99;
cout << "TEST RESIZE: " << a << endl << endl;
}
Any help is appreciated
Currently when I run this I get the error:
Debug Assertion Failed!
Expression:_CrtIsValiedHeadPointer(block)
Assuming _theArray is a class member variable, you can do _theArray = nArray after the call to destroy() and delete the last 2 lines involving p.
I am having some issues with an array expansion project and am trying to find where the issue is with getting my array to expand with all zeroes. Here are the requirements:
Array Expander. The program should have an array of integers. It will have a function that has two parameters, the integer array and the array’s size. This function will create a new array that is twice the size of the arguments array. The function should copy the contents of the argument array to the new array, and initialize the unused elements of the second array with 0. The function must return a pointer to the new array. The program will then display the contents of the new array.
Program must have the following functions
• int* expandArray(int[ ], int)
• void showArray(int [ ], int)
I am getting the program to build the first array without issues, however, the second array, while it displays the first array of numbers fine, displays the second array with an assortment of digits. I have been looking at this for hours and am at a loss with how to correct this to work correctly. Here is my code that I have so far:
//Include section
#include <iostream>
#include <cstring>
//Namespace Section
using namespace std;
//Function Prototype Section
int *expandArray(int[], int&);
void showArray(const int[], int);
//Main section: this is the entry point of the program, which controls the flow of execution
int main()
{
int arraySize = 7; //sets the size of the array at 7
int *array = new int[arraySize];
for (int c = 0; c < arraySize; ++c)
array[c] = c + 1;
//the following outputs the initial array of 7 to the user's screen; beginning at 1 and incrementing to 7
cout << "*********************************************************************" << endl;
cout << " The following is the initial array " << endl;
cout << "*********************************************************************" << endl;
cout << endl;
showArray(array, arraySize);
cout << endl;
cout << endl;
//the following outputs the initial array, plus expands the array by double, initializing the unused elements with zero
cout << "*********************************************************************" << endl;
cout << " The following is the expanded array " << endl;
cout << "*********************************************************************" << endl;
cout << endl;
showArray(array, arraySize * 2);
cout << endl;
cout << endl;
delete[] array;
system("PAUSE");
return 0;
}
int *expandArray(int array[], int &arraySize)
{
int *expandedArray;
expandedArray = new int[arraySize * 2];
for (int index = arraySize; index < (arraySize * 2); index++)
expandedArray[index] = 0;
arraySize *= 2;
delete[] array;
return expandedArray;
}
void showArray(const int arr[], int arraySize)
{
for (int index = 0; index < arraySize; index++)
cout << arr[index] << " " << endl;
}
I believe my issue is in the following section of the code, but unsure as to how to fix it:
int *expandArray(int array[], int &arraySize)
{
int *expandedArray;
expandedArray = new int[arraySize * 2];
for (int index = arraySize; index < (arraySize * 2); index++)
expandedArray[index] = 0;
arraySize *= 2;
delete[] array;
return expandedArray;
Any assistance would be greatly appreciated!
As I see it you forgot to to copy the contents of your initial array into expandedArray in the declaration of your function. You only set all elements with index in between arraySize and arraySize*2 to 0 but never actually copied the values of your argument.
I would include the following:
for(int i=0; i<arraySize; i++) expandedArray[i] = array[i];
right after having declared expandedArray dynamically. Note it is important that you include this piece of code before modifying arraySize as you would get out-of-bounds issues when accessing array[i].
The issue is that you're not copying the original array's contents into the new allocated array space.
A simple solution is to use new[] with brace initialization of 0, and then copy the original contents into the new array. The brace initialization will initialize all the space to 0, so you don't need to write two loop to set the newly allocated space to 0.
int *expandArray(int array[], int &arraySize)
{
int *expandedArray;
// allocate and initialize all entries to 0
expandedArray = new int[arraySize * 2]{0};
// copy old elements to new space
for (int index = 0; index < arraySize; index++)
expandedArray[index] = array[index];
// delete old space
delete [] array;
// double array size
arraySize *= 2;
return expandedArray;
}
int *arrayExpander(int arr[], int size)
{
int *expendedArray = new int[size * 2];
// move elements forom original array into the expandedArray
// initilize the rest of the elements to ZERO
for (int i = 0; i < size * 2; i++)
{
if (i < size)
{
// filling firt half
expendedArray[i] = arr[i];
}
else
{
// second half of the array
expendedArray[i] = 0;
}
}
return expendedArray;
}
int main()
{
int size = 5;
int arr[] = { 1,2,3,4,5 };
// Array pointer
int *arrPtr = arrayExpander(arr, size);
// Display
for (int i = 0; i < size * 2; i++)
{
cout << arrPtr[i] << " " << flush;
}
return 0;
}
Actually there are 2 errors in your code:
When you run your code it prints the first 7 elements of your array of type double correctly, but not the other 7. This is because they are not initialized, therefore they are returning garbage values.
Therefore in the function you have to initialize the other 7 elements to 0. The same goes for the first 7 elements and the first matrix.
I rectified the problem. Please have a good look at it:
//Include section
#include <iostream>
#include <cstring>
//Namespace Section
using namespace std;
//Function Prototype Section
int *expandArray(int[], int&);
void showArray(const int[], int);
int *expandedArray;
//Main section: this is the entry point of the program, which controls the flow of execution
int main()
{
int arraySize = 7; //sets the size of the array at 7
int *array = new int[arraySize];
for (int c = 0; c < arraySize; ++c)
array[c] = c + 1;
//the following outputs the initial array of 7 to the user's screen; beginning at 1 and incrementing to 7
cout << "*********************************************************************" << endl;
cout << " The following is the initial array " << endl;
cout << "*********************************************************************" << endl;
cout << endl;
showArray(array, arraySize);
cout << endl;
cout << endl;
//the following outputs the initial array, plus expands the array by double, initializing the unused elements with zero
cout << "*********************************************************************" << endl;
cout << " The following is the expanded array " << endl;
cout << "*********************************************************************" << endl;
cout << endl;
expandArray(array, arraySize);
showArray(expandedArray, arraySize);
cout << endl;
cout << endl;
delete[] array;
return 0;
}
int *expandArray(int array[], int &arraySize)
{
expandedArray = new int[arraySize * 2];
for (int c = 0; c < arraySize; ++c)
expandedArray[c] = c + 1;
for (int index = arraySize; index < (arraySize * 2); index++)
expandedArray[index] = 0;
arraySize *= 2;
delete[] array;
return expandedArray;
}
void showArray(const int arr[], int arraySize)
{
for (int index = 0; index < arraySize; index++)
cout << arr[index] << " " << endl;
}
//here is your solution bro..!!