Memory allocation with operator new and initialization with data - c++

In my project, there are one million inputs and I am supposed to compare search/sort algorithms with different numbers of inputs untill one million inputs. I want to do memory allocation and initialization with data together but I reailized it is not possible. So I decided to do like this;
double temp1, temp2, temp3; //Each line has three numbers
int i;
Person *list[N]; //Here, stackoverflow occurs, for example N=500000
for(i=0; i<N; i++){
file >> temp1 >> temp2 >> temp3;
list[i] = new Person(temp1, temp2, temp3); //I wanted to initialize with data
} //but if I wrote "new Person[N]"
//stackoverflow doesn't occur
But there is an overflow with huge numbers, for example N = 500000.
So, is there any method which combine these two?(Without overflow and with data initialization)
Secondly, is there any difference between these two code;
Person *list[N];
for(i=0; i<N; i++){
list[i] = new Person();
}
Person *list = new list[N];

As a beginner, it's best to avoid using your own containers. You can just use the Standard-provided ones:
...
#include <vector>
#include <cstdlib> // for EXIT_FAILURE, EXIT_SUCCESS
double temp1, temp2, temp3; //Each line has three numbers
std::vector<Person> people;
for(int i=0; i<N; i++)
if (file >> temp1 >> temp2 >> temp3)
people.emplace_back(temp1, temp2, temp3);
else
{
std::cerr << "error reading 3 numbers from file, terminating\n";
exit(EXIT_FAILURE);
}
It's especially useful to use vector (or new Person[n], and in contrast to new Person*[n]) to keep the data together (contiguous) in memory, so your CPU gets the maximum possible benefit from its caches during the searching and sorting that you want to compare... if your data's harder to access it'll hide the extent of performance difference between the algorithms under test. With new Person*[n] and every Person object being allocated on the heap, the data gets scattered and can be much slower to access.
Just to explain what was happening with your current code:
you were trying to put too much data on the stack; you can work around that by having a single stack-hosted pointer to the required amount of dynamically allocated memory (it's normal for an application to have massively more dynamic memory available than stack space).
Secondly, is there any difference between these two code;
Person* list[N]; // first
for(i=0; i<N; i++){
list[i] = new Person();
}
Person *list = new Person[N]; // second - corrected from "new list[N}"
The first asks for an array of Person*s on the stack, then assigns each of those pointers to a distinct dynamically-allocated memory address. At best, that will use almost as much stack memory - and at worst around double - as trying to put Person list[N]; directly on the stack and is likely to fail the same way. It also scatters the Person data around in dynamic memory, and operations on the data will be unnecessarily slow.
The second creates one dynamically-allocated memory region big enough for N Persons, and keeps a single pointer to it on the stack. That's not unreasonable (but std::vector's still a better idea).

In your example,
Person *list[N];
is created as a local variable on the stack. 500,000 pointers would take up about 2 MB - which is likely to exceed the stack size on some machines. http://msdn.microsoft.com/en-us/library/windows/desktop/ms686774(v=vs.85).aspx
However,
//Person *list = new list[N];
Person **list = new Person* [N];
will create your array on the heap, and you should be able to allocate that without running out of memory. However, each Person object will have a size and require allocation in addition to the array of pointers.

Related

Freeing memory between loop executions

Hi I'm coding a C++ program containing a loop consuming too much unnecessary memory, so much that the computer freezes before reaching the end...
Here is how this loop looks like:
float t = 0.20;
while(t<0.35){
CustomClass a(t);
a.runCalculations();
a.writeResultsInFile("results_" + t);
t += 0.001;
}
If relevant, the program is a physics simulation from which I want results for several values of an external parameter called t for temperature. It seems that the memory excess is due to not "freeing" the space taken by the instance of my class from one execution of the loop to the following, which I thought would be automatic if created without using pointers or the new instruction. I tried doing it with a destructor for the class but it didn't help. Could it be because the main memory use of my class is a 2d array defined with a new instruction in there?
Precision, it seems that the code above is not the problem (thanks for the ones pointing this out) so here is how I initiate my array (by the largest object in my CustomClass) in its constructor:
tab = new int*[h];
for(int i=0; i<h; i++) {
tab[i] = new int[v];
for(int j=0; j<v; j++) {
tab[i][j] = bitd(gen)*2-1; //initializing randomly the lattice
}
}
bitd(gen) is a random number generator outputing 1 or 0.
And also, another method of my CustomClass object doubles the size of the array in the following way:
int ** temp = new int*[h];
for(int i=0; i<h; i++) {
temp[i] = new int[v];
for(int j=0; j<v; j++) {
temp[i][j] = tab[i/2][j/2];
}
}
delete[] tab;
tab = temp;
Could there be that I should free the pointer temp?
You're leaking memory.
Could there be that I should free te pointer temp?
No. After you allocate the memory for the new array of double size and copy the contents, you should free the memory that tab is pointing to. Right now, you're only deleting the array of pointers with delete [] tab; but the memory that each of those pointers points to is lost. Run a loop and delete each one. Only then do tab = temp.
Better still, use standard containers that handle memory management for you so you can forget messing with raw pointers and focus on your real work instead.

copy matrix into where pointer points to in c++

How to copy a matrix into where a pointer points to?
I am new in c++. I tried a lot but I could not find any solution.
here is my code:
float *output = new float[HighRange];
output = new float[10 * 10];
for(int i=0; i<10; i++){
for(int j=0; j<10; j++){
output[j]=input[i][j]; ---> I have error in this line
Thanks in advance
There are several ways to arrange the elements of input in output. Here is one way:
output[i*10 + j] = input[i][j]
Aside from NPEs suggestion, you have a memory leak here:
float *output = new float[HighRange]; // allocate contiguous block HighRange * sizeof(float) bytes
output = new float[10 * 10]; // allocate contiguous block 100 * sizeof(float) bytes
Aside from this being unnecessary, you leak memory, i.e. you allocate storage in the first statement that you never free before assigning a new value to the pointer that hold the first address to the previously allocated storage.
When allocating memory dynamically using new, you need to make sure you delete it accordingly. For arrays, you need to do the following:
float *output = new float[HighRange]; // allocate
delete [] output; // deallocate, note the delete[] operator
output = new float[10 * 10]; // allocate anew
Note: This is just to display correct usage of new/delete[]. By no means do I suggest your code would be any better if you handled deallocation in your example. :)

C++ inserting (and shifting) data into an array

I am trying to insert data into a leaf node (an array) of a B-Tree. Here is the code I have so far:
void LeafNode::insertCorrectPosLeaf(int num)
{
for (int pos=count; pos>=0; pos--) // goes through values in leaf node
{
if (num < values[pos-1]) // if inserting num < previous value in leaf node
{continue;} // conitnue searching for correct place
else // if inserting num >= previous value in leaf node
{
values[pos] = num; // inserts in position
break;
}
}
count++;
} // insertCorrectPos()
Before the line values[pos] = num, I think need to write some code that shifts the existing data instead of overwriting it. I am trying to use memmove but have a question about it. Its third parameter is the number of bytes to copy. If I am moving a single int on a 64 bit machine, does this mean I would put a "4" here? If I am going about this completely wrong any any help would be greatly appreciated. Thanks
The easiest way (and probably the most efficient) would be to use one of the standard libraries predefined structures to implement "values". I suggest either list or vector. This is because both list and vector has an insert function that does it for you. I suggest the vector class specifically is because it has the same kind of interface that an array has. However, if you want to optimize for speed of this action specifically, then I would suggest the list class because of the way it is implemented.
If you would rather to it the hard way, then here goes...
First, you need to make sure that you have the space to work in. You can either allocate dynamically:
int *values = new int[size];
or statically
int values[MAX_SIZE];
If you allocate statically, then you need to make sure that MAX_SIZE is some gigantic value that you will never ever exceed. Furthermore, you need to check the actual size of the array against the amount of allocated space every time you add an element.
if (size < MAX_SIZE-1)
{
// add an element
size++;
}
If you allocate dynamically, then you need to reallocate the whole array every time you add an element.
int *temp = new int[size+1];
for (int i = 0; i < size; i++)
temp[i] = values[i];
delete [] values;
values = temp;
temp = NULL;
// add the element
size++;
When you insert a new value, you need to shift every value over.
int temp = 0;
for (i = 0; i < size+1; i++)
{
if (values[i] > num || i == size)
{
temp = values[i];
values[i] = num;
num = temp;
}
}
Keep in mind that this is not at all optimized. A truly magical implementation would combine the two allocation strategies by dynamically allocating more space than you need, then growing the array by blocks when you run out of space. This is exactly what the vector implementation does.
The list implementation uses a linked list which has O(1) time for inserting a value because of it's structure. However, it is much less space inefficient and has O(n) time for accessing an element at location n.
Also, this code was written on the fly... be careful when using it. There might be a weird edge case that I am missing in the last code segment.
Cheers!
Ned

Creating an Array of Structures on the Heap in C++

I need to declare an array of structures on the heap, then transfer data from parallel arrays on the stack and from calculations into each structure. I declared
struct Grades
{
string studentName;
int scores[4];
double average;
};
....
Grades *art1301 = new Grades;
....
(art1301 + i)->studentName = names[i];
for((int i = 0 ; i < 5 ; i++ )
(art1301 + i)->scores[j] = exams[i][j];
(art1301 + i)->average = average;
My program accesses the first record, but it crashes after it accesses the first field of the second record. I don't understand why it works for the first record, but dies in the middle of the second? Am I accessing the structure correctly?
Thank you.
To allocate an array, you need the array form of new, with the square brackets:
Grades *art1301 = new Grades[200];
// ^^^^^
The array size can be a dynamically determined quantity.
You aren't allocating memory for an array, you are allocating only for one element.
As someone said in the comments, the key is in the new Grades instruction
In addition, unless you have another i variable declared before (which is a bad practice), that code doesn't compile because (art1301 + i)->studentName = names[i]; will not find variable i

Different outputs after debugging and compiling C++ programs

I'm running CodeBlocks on the MingW compiler in an XP virtual machine. I wrote in some simple code, accessible at cl1p , which answers the algorithm question at CodeChef (Well it only answers it partly, as I have not yet included the loop for multiple test cases.
However, my problem is, that while running it in debug mode, it gives the correct output of 5, for the input:
3
1
2 1
1 2 3
However, when I build and run it, it gives the absurd, huge output 131078, what seems like garbage to me. I do not understand how the hell this is happening, but am guessing it's something to do with the dynamic memory allocation. What's the problem here, and how can I fix it? I even ran it through the online compiler at BotSkool, and it worked fine. After adding the loop for test cases, the code even worked correctly on CodeChef!
#include <iostream>
using namespace std;
int main()
{
// Take In number of rows
int numofrows;
cin >> numofrows;
// Input Only item in first row
int * prevrow;
prevrow = new int[1];
cin >> prevrow[0];
// For every other row
for (int currownum = 1; currownum < numofrows; currownum++)
{
// Declare an array for that row's max values
int * currow;
currow = new int[currownum+1];
int curnum;
cin >> curnum;
// If its the first element, max is prevmax + current input
currow[0] = prevrow[0] + curnum;
// for every element
int i = 1;
for (; i <= currownum; i++)
{
cin >> curnum;
// if its not the first element, check whether prevmax or prev-1max is greater. Add to current input
int max = (prevrow[i] > prevrow[i-1]) ? prevrow[i] : prevrow[i-1];
// save as currmax.
currow[i] = max + curnum;
}
// save entire array in prev
prevrow = new int[i+1];
prevrow = currow;
}
// get highest element of array
int ans = 0;
for (int j=0; j<numofrows; j++)
{
if (prevrow[j] > ans)
{
ans = prevrow[j];
}
}
cout << ans;
}
Run the code through Valgrind on a Linux machine and you'll be amazed at how many places your code is leaking memory.
If you are taking the hard road of managing your memory, do it well and 'delete' all the new-allocated memory before allocating more.
If, on the other hand, you prefer the easy road, use a std::vector and forget about memory management.
For one thing, this:
//save entire array in prev
prevrow = new int [i+1];
prevrow = currow;
copies the pointer, not the whole array.
In your loop, you have this line
int max = (prevrow[i]>prevrow[i-1])?prevrow[i]:prevrow[i-1];
On the first iteration of the main loop, when currownum == 1, the loop containing this line will be entered, as i is initialized to 1. But on the first iteration, prevrow only has one element and this line tries to access prevrow[1]. In a debug build, the memory simply gets initialized to zero, but in a normal build, you get some garbage value that just happened to be in the memory, leading to the result you see.
Pretty much always, when you get garbage values in a normal build, but everything is fine in a debug build, you are accessing some uninitialized memory.
Also, your program is leaking memory like crazy. For instance, you don't need to assign any result of new inside the loop to prevrow because right after that you change prevrow to point to another block of allocated memory. Also, you should call delete for any memory that you are no longer using.