I have to create a program that uses the 'new' operator to create a dynamic array in heap of the program. The program creates and populates its dynamic array one (int) elements at a time for each input data (cin).
Key parts.
1.) Program has to used "cin >>" for data input to accept on integer at a time until EOF is pressed on the keyboard (cntrl-z for windows).
2.) User input has to be tested using !cin.eof() && cin.good() to test whether or not the EOF key was pressed and if the data is valid. (kinda of confused about the cin.good() part).
3.) The program will create a series of longer and longer arrays to contain all previous elements and the current incoming one. Also, the program will delete the previous version of the array after completing the current version.
4.) The program also tests if heap memory has been exhausted after each use of the new operator. (need help with this)
I keep getting error message "HEAP CORRUPTION DETECTOR After normal black (#146)" (visual studio). What's the issue?
Thanks in advance!
Here's the code:
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <cassert>
using namespace std;
// main
int main() {
int size = 2;
int * array1 = new int[size];
int arrayInput;
int count = 0;
do {
if (array1 != NULL) {
cout << "Enter an integer (EOF to stop): " << endl;
cin >> arrayInput;
if (size < count) {
int * tempArray;
tempArray = new int[size * 2];
if (tempArray != NULL)
{
for (int i = 0; i < size; i++) {
array1[i] = tempArray[i];
}
delete[] array1;
array1 = tempArray;
size *= 2;
delete [] tempArray;
}
else
cout << "Insufficient Heap resource." << endl; // If we get here the Heap is out of space
}
if (!cin.eof()) {
array1[count++] = arrayInput;
}
}
else
cout << "Insufficient Heap resource." << endl; // If we get here the Heap is out of space
} while (!cin.eof());
for (int i = 0; i < count; i++) {
cout << array1[i] << endl;
}
}
tempArray = new int[size * 2];
if (tempArray != NULL)
{
for (int i = 0; i < size; i++) {
array1[i] = tempArray[i];
}
You allocate a new array twice as big as your old array. Then you copy the contents of the newly allocated array into your existing array. The newly-allocated array contains random garbage, that you just used to override the existing, good data, in your old array.
That's one obvious bug, but it won't explain the crash.
delete[] array1;
array1 = tempArray;
size *= 2;
delete [] tempArray;
After copying, you delete your old array. Then you also delete your new array, that you just allocated. That smells like another bug, but it still won't explain the crash.
if (!cin.eof()) {
array1[count++] = arrayInput;
}
Now, you can answer your own question here: what happens when you continue to write to a pointer that was pointing to memory that you freed, recently?
That are multiple bugs in the shown code. They all must be fixed. I haven't looked further, past this point. There might still be other issues with this code. A rubber duck should be able to help you to find any remaining bugs in your program.
Related
I created a class that mimics the action of C++ vector by creating a dynamic array, I try to create a push back method for that class which first checks if the array is filled, if so it will:
1- Copy the contents of current array to a temporary array with the double size
2- Delete the old dynamic array
3- Create a new dynamic array with the double size of the old array (same size of temporary array)
4- Copy contents of the temporary array to the new dynamic array
the error is while I use the following code, I can only double the size of array once, then it throws to error:
HEAP[ConsoleApplication1.exe]: Invalid address specified to RtlValidateHeap( 016C0000, 016CDB98 )
ConsoleApplication1.exe has triggered a breakpoint.
#include <iostream>
using namespace std;
class SimpleVector {
private:
int* item; //pointer to the dynamic array (the vector)
int size;
int numElements;
public:
SimpleVector(int size) {
this->size = size;
this->numElements = 0;
this->item = new int[this->size];
}
SimpleVector():SimpleVector(10){}
void pushBack(int element) {
//check for overflow
if (numElements >= size) {
int newSize = size * 2;
int* temp = new int[newSize]; // temporary array with the double size to hold old array elements
for (int i = 0; i < numElements; i++) {
temp[i] = item[i];
}
delete[] item;
size = newSize;
//****ERROR IS IN THIS PART****
int* item = new int[size];
for (int i = 0; i < numElements; i++) {
item[i] = temp[i];
}
//****END OF THE PART CONTAINING ERROR****
item[numElements++] = element;
cout << "Added: " << element << endl;
cout << "Size is: " << size << endl;
}
else {
item[numElements++] = element;
cout << "Added: " << element << endl;
cout << "Size is: " << size << endl;
}
}
};
int main() {
SimpleVector v1(2);
v1.pushBack(1);
v1.pushBack(2);
v1.pushBack(3);
v1.pushBack(4);
v1.pushBack(5);
v1.pushBack(6);
v1.pushBack(7);
return 0;
}
This program pushs the first 4 items and then throws into error when trying to double the size form to 8
when I just replace that part containing error with:
item = temp
it works fine, but I can't understand why this happens.
Your code has several problems. I suggest you read about how to properly comply with Rule of Three/Five/Zero , which I'm not going to cover here. I only imagine this is for some nefarious academic purpose, so I will try to be brief, but please read the linked article.
That said, this:
int *item = new int[size];
for (int i = 0; i < numElements; i++)
{
item[i] = temp[i];
}
is pointless. This starts a cascade of bad actions that only gets worse as it rolls along.
You already have a member variable item. This code declares a local variable named item whose name hides the member item. Therefore the initialized value from the new operator is stored in the local, not the member.
That memory now pointed to by the local var item (not the member) is lost on exit of the function, since nothing but the local item ever points to it.
That additional allocation is pointless to begin with. You already made a new vector copy, pointed to by temp, and already copied all the legitimate items from memver-var item memory to temp memory. The code as-written leaks that temp allocation as well.
You destroy the member-var item memory, leaving the pointer now dangling, and any usage thereafter by dereference or eval invokes undefined behavior.
So, in summary, you make a valuable extended copy, leak it, make a worthless copy, leak it too, and end up leaving with a member variable that is no longer pointing at anything defined.
That entire function could look more like this:
void pushBack(int element)
{
// check for overflow
if (numElements >= size)
{
int newSize = size * 2;
int *temp = new int[newSize];
for (int i = 0; i < numElements; i++)
{
temp[i] = item[i];
}
delete[] item;
size = newSize;
item = temp;
}
item[numElements++] = element;
cout << "Added: " << element << endl;
cout << "Size is: " << size << endl;
}
I'm trying to create a 2D array of c-strings (for a specific school exercise; I'm forced to use c-strings for practice) using dynamic memory allocation. However, it seems that when accessing and writing to the second index of the array (second sub-array), the actual memory location that's used is the same of the first index.
The code:
#include <iostream>
#include <string>
int main()
{
int n_names; std::string current; const int SPACE_FOR_EACH_NAME = 100;
std::cout << "How many names to input? "; std::cin >> n_names; std::cin.ignore();
//dynamically allocate a multi-dimensional array
char** names;
names = new char* [n_names];
for (int i = 0; i < n_names; i++)
names[i] = new char[SPACE_FOR_EACH_NAME];
int count = 0;
while (count < n_names) {
std::cout << "Name " << ++count << ": ";
std::getline(std::cin, current);
names[count-1] = (char*) current.c_str(); //THE TROUBLE SEEMS TO BE HERE
}
for (int i = 0; i < n_names; ++i) {
for (int j = 0; j < SPACE_FOR_EACH_NAME; ++j) {
if (names[i][j] == '\0') break; //termination of the current name
std::cout << names[i][j];
}
std::cout << "\n";
}
//free allocated memory
for (int i = 0; i < n_names; ++i)
delete[] names[i];
delete[] names;
}
What the debugger shows when modifying the 'names' array (consider user inputs 2 names):
+ names[count-1] 0x00affbe8 "dude" char * //here count is 1
+ names[count-1] 0x00affbe8 "noice" char * //here count is 2
And the console just prints "noice" twice.
What's wrong?
The result of current.c_str() should never be stored for any length of time. Doing so is undefined behaviour, but it is likely, as here that that memory pointed to will be reused.
You put the char* from current.c_str() into names[0], then you put a new value into current and put current.c_str() into names[1]. But because you have changed current you also change names[0].
Also, in both cases, you are discarding the pointer you already created with names[i] = new char[SPACE_FOR_EACH_NAME];
This allocates a block of memory and puts it's address into names[0] (0 as a specific example). The next thing that happens with names[0] is names[0] = (char*) current.c_str(); which puts a different address into the variable. The address returned from the new is lost completely, causing a memory leak.
Instead of
names[count-1] = (char*) current.c_str();
try
std::strcpy(names[count-1],current.c_str())
I created this function to change the size of the dynamic array
size = 4; //this is what size is in my code
int *list = new int[size] // this is what list
void dynArray::doubleSize( )
{
int *temparray;
int currentsize = size;
int newsize = currentsize * 2;
temparray = new int[newsize];
for (int i = 0 ; i < newsize;i++)
{
temparray[i] = list[i];
}
size = newsize;
delete [] list;
list = new int[size];
list = temparray;
// this it help see if i made any changes
cout << sizeof(temparray) << "temp size:\n";
cout << sizeof(list) << "list size:\n";
cout << size << "new size:\n\n\n";
}
I want it to output the size of array is the function each time it changes size.I know this can be done with vectors but I would like to understand how to do it with arrays
what can I do differently to make this happen.
You can't: the C++ Standard provides no mechanism to access dynamic array dimensions. If you want to know them, you have to record them when creating the array, then look at the variables you set (much as you've got size hanging around for printing at the end of your program.
Problems in your code:
Problem 1
The following for loop accesses list using out of bound indices. Number of element in list is size, not newSize.
for (int i = 0 ; i < newsize;i++)
{
temparray[i] = list[i];
}
You need to change the conditionals to i < size;.
Then, you need to figure out how how to initialize the rest of the items in temparray.
Problem 2
The following lines cause a memory leak.
list = new int[size];
list = temparray;
You allocate memory using new and immediately lose that pointer in the second line.
Answer to your question
To print the new size, you can use:
cout << "new size: " << size << "\n";
However, I wouldn't recommend putting such code in that function. You are making your class dependent on std::cout for not much benefit, IMO.
I am trying to write code in C++ that reads from a file, a sequence of points, stores it in a dynamic array and then prints back.
This is the specification I've been given:
"We want to take advantage of the fact that we can use dynamic memory, thus instead of allocating at beginning an amount of memory large enough according to our estimations, we implement the following algorithm:
Initially, very little memory is allocated.
At each iteration of the loop (reading from the file and storing into the
dynamic array) we keep track of:
The array maximum size (the allocated memory).
The number of elements in the array.
When, because of a new insertion, the number of elements would become
greater than the array maximum size, memory reallocation needs to take
place as follows:
Allocate another dynamic array with a greater maximum size.
Copy all the elements from the previous array to the new one.
Deallocate the memory area allocated for the previous array.
Get the pointer to the previous array to point to the new one.
Add the new item at the end of the array. This is where my problem is.
From my code below, I think everything else is fine but the last requirement, which is to add the new item at the end of the array.
The code works fine when the array Max_Size exceeds file's number of
elements, but when I try extending the num_elements, the result is
that the extra digits in the file are just saved as zeros
.
Also to add, the assignment doesn't allow use of vectors just yet.
Sorry I forgot to mention this, I'm new to stackoverflow and somewhat
to programming.
Any help please
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
struct point {
double x;
double y;
};
int main () {
ifstream inputfile;
inputfile.open("datainput.txt");
if(!inputfile.is_open()){
cout << "could not open file" << endl;
exit(EXIT_FAILURE);
}
//initially very little memory is allocated
int Max_Size = 10;
int num_elements = 0;
point *pp = new point[Max_Size];
//read from file and store in dynamic array
for (int i = 0; !inputfile.eof(); i++) {
inputfile >> pp[i].x >> pp[i].y;
num_elements++; //keep track of number of elements in array
}
//detecting when number of elements exeeds max size due to new insertion:
if (num_elements > Max_Size){
// allocate another dynamic array with a greater maximum size
Max_Size *= 2; // Max_Size = 2*Max_Size to double max size whenever there's memory problem
point *pp2 = new point[Max_Size];
//copy all elements from previous array to new one
for (int j=0; j<(Max_Size/2); j++) {
pp2[j].x = pp[j].x ;
pp2[j].y = pp[j].y;
}
//deallocate memory area allocated for previous array
delete [] pp;
//get pointer to previous array to point to the new one
pp = pp2;
**//add new item at end of the array
for (int k = ((Max_Size/2)-1); k<num_elements; k++) {
inputfile.seekg(k, ios::beg) >> pp2[k].x;
inputfile.seekg(k, ios::beg) >> pp2[k].y;
}**
//print out dynamic array values
for (int l = 0; l<num_elements; l++) {
cout << pp2[l].x << ",";
cout << pp2[l].y << endl;
}
//delete dynamic array
delete [] pp2;
}
else {
//print out dynamic array values
for (int m = 0; m<num_elements; m++) {
cout << pp[m].x << ",";
cout << pp[m].y << endl;
}
//delete dynamic array
delete [] pp;
}
cout <<"Number of elements = " << num_elements <<endl;
//close file
inputfile.close();
return 0;
}
Others have already pointed out std::vector. Here's roughly how code using it could look:
#include <vector>
#include <iostream>
struct point {
double x;
double y;
friend std::istream &operator>>(std::istream &is, point &p) {
return is >> p.x >> p.y;
}
friend std::ostream &operator<<(std::ostream &os, point const &p) {
return os << p.x << "," << p.y;
}
};
int main() {
// open the file of data
std::ifstream in("datainput.txt");
// initialize the vector from the file of data:
std::vector<point> p {
std::istream_iterator<point>(in),
std::istream_iterator<point>() };
// print out the data:
std::copy(p.begin(), p.end(), std::ostream_iterator<point>(std::cout, "\n"));
}
On top of being a lot shorter and simpler than the code you posted, getting this to work is likely to be a lot simpler and (as icing on the cake) it will almost certainly run faster1 (especially if you have a lot of data).
1. In fairness, I feel obliged to point out that the big difference in speed will mostly come from using \n instead of endl to terminate each line. This avoids flushing the file buffer as each line is written, which can easily give an order of magnitude speed improvement. See also: https://stackoverflow.com/a/1926432/179910
The program logic is flawed. You run the loop until EOF but you don't check to see if you have exeeded your array size. I would add an if statement inside of the first loop to check if you have passed the Max_Size. I would also write a function to reallocate the memory so you can simply call that function inside of your first loop.
Also you have problems with your memory allocation. You should do like this:
point temp = pp;
pp = new Point[...];
// Copy the contents of temp into pp
delete temp;
You need to set your pointer to the old array first so you don't lose it. Then after you have copied the contents of you old array into the new array, you can then delete the old array.
Let's say I have a dynamic array:
int* p;
ifstream inFile("pop.txt");
int x;
while (inFile >> x)
{
// ????
}
How do I resize p so I am able to to fit x in as like an array. I don't want to use a vector or static array as I am trying to learn the language. I need to use pointers because I don't know the initial size. Any attempt is appreciated.
The simplest answer is that you should use higher level components than raw arrays and raw memory for the reading. That way the library will handle this for you. A simple way of reading a set of numbers into an application (without error handling) could be done with this simple code:
std::vector<int> data;
std::copy(std::istream_iterator<int>(inFile), std::istream_iterator<int>(),
std::back_inserter(data));
The code creates a couple of input iterators out of the stream to read int values, and uses a back_inserter iterator that will push_back onto the vector. The vector itself will manage growing the memory buffer as needed.
If you want to do this manually you can, you just need to allocate a larger chunk of memory, copy the first N elements from the old buffer, release the old buffer and continue reading until the larger buffer gets filled, at which point you follow the same procedure: allocate, copy, deallocate old, continue inserting.
You can't resize it. All you can do is allocate a new bigger array, copy everything over from the old array to the new array, then free the old array.
For instance (untested code)
int array_size = 10;
int* array = new int[array_size];
int array_in_use = 0;
int x;
while (in >> x)
{
if (array_in_use == array_size)
{
int* new_array = new int[2*array_size];
for (int i = 0; i < array_size; ++i)
new_array[i] = array[i];
delete[] array;
array = new_array;
array_size *= 2;
}
array[array_in_use++] = x;
}
It's tedious, and I'm not convinced it's a good thing for a beginner to be doing. You'd learn more useful stuff if you learned how to use vectors properly.
You could always use realloc(). It's a part of the C Standard Library, and the C Standard Library is a part of the C++ Standard Library. No need for tedious news and deletes.
#include <cstdlib>
#include <iostream>
#include <fstream>
int main(void)
{
int* array = nullptr;
unsigned int array_size = 0;
std::ifstream input("pop.txt");
for(int x; input >> x;)
{
++array_size;
int* array_failsafe = array;
array = static_cast<int*>(realloc(array, sizeof(x) * array_size));
if(array == nullptr)
{
std::cerr << "realloc() failed!" << std::endl;
free(array_failsafe);
return EXIT_FAILURE;
}
array[array_size-1] = x;
}
for(unsigned int i = 0; i < array_size; ++i)
{
std::cout << "array[" << i << "] = " << array[i] << std::endl;
}
free(array); // Don't forget!
return EXIT_SUCCESS;
}