XCode: Stack Size Limit on Multidimensional Array - c++

i have some complex classes in my xcode project (below a generic example)
and it seems I have hit some sort of data size limit.
the array sizes I need do not work, if I reduze the array sizes the code works (so no programming errors), but it is too small for what I planned.
reading through the internet I figured out it must be a problem with stack size and most of the solutions say "convert your static arrays to dynamic arrays".
but (1) that is not that easy with multidimensional arrays (some up to 5 to 10 dimensions as they monitor multiple independent variables and each combination is possible)
and (2) are most of the arrays nested in several classes, making it even worse.
I thought already of reducing the data
int instead of long with some intelligent transposition...
change resolution of c (0-100%) into steps of 10% (so [100] reduces to [10])
but on one hand this might jeopardize the overall results and on the other is the project still at the start so it will grow in the next month... this array size problem will come back sooner or later...
here I generalized the code showing a 4 dimensional array (2x 2D).
I guess most professional programs use arrays that are even bigger.
so there must be a way to make this works...
//.h
class StatisticTable
{
public:
long Array1 [100][50];
long Array2 [100][50];
long Array3 [100][140];
};
class Statistic
{
public:
void WriteStatistic(short Parameter_a, short Parameter_b,
short Parameter_c, short Parameter_d);
short ReadStatistic(short Parameter_a, short Parameter_b,
short Parameter_c, short Parameter_d);
private:
StatisticTable Table[16][8];
};
//.cpp
void WriteStatistic(short a, short b, short c, short d)
{
for (int i=0; i<d, i++) {Table[a][b].Array1[c][i]++;}
for (int i=d; i<50, i++) {Table[a][b].Array2[c][i]++;}
//write some more stuff
return;
}

Can you use heap allocation instead of stack allocation?
As suggested, using std::unique_ptr:
auto const ptr = std::unique_ptr<StatisticTable>(new StatisticTable()).get(); // heap allocated and deleted automatically when obj goes out of scope
I.e.
auto obj = new StatisticTable(); // heap allocation, allocate reference to new StatisticTable object on heap
// code
delete obj; // release heap allocated object
vs.
auto x = StatisticTable() // stack allocation

Related

Memory limit in int main()

I need to make a big array in one task (more than 10^7).
And what I found that if i do it int main the code wouldnt work (the program will exit before doing cout "Process returned -1073741571 (0xC00000FD)").
If I do it outside everything will work.
(I am using Code::Blocks 17.12)
// dont work
#include <bits/stdc++.h>
using namespace std;
const int N = 1e7;
int main() {
int a[N];
cout << 1;
return 0;
}
// will work
#include <bits/stdc++.h>
using namespace std;
const int N = 1e7;
int a[N];
int main() {
cout << 1;
return 0;
}
So I have questions:
-Why it happens?
-What can I do to define array in int main()? (actually if i do vector same size in int main() everything will work and it is strange)
There are four main types of memory which are interesting for C++ programmers: stack, heap, static memory, and the memory of registers.
In
const int N = 1e7;
int main(){int a[N];}
stack memory is deployed.
This type of memory is usually more limited than the heap and the static memory in size. For that reason, the error code is returned.
Operator new (or other function which allocates memory in heap) is needed so as to use heap:
const int N = 1e7;
int main(){int* a = new int[N]; delete a;}
Usually, the operator new is not used explicitly.
std::vector uses heap (i.e. it uses new or something of the lower level underneath) (as opposed to the std::array or the C-style array, e.g. int[N]). Because of that, std::vector is usually capable of holding bigger chunks of data than the std::array or the C-style array.
If you do
const int N = 1e7;
int a[N];
int main(){}
static memory is utilized. It's usually less limited in size than the stack memory.
To wrap up, you used stack in int main(){int a[N];}, static memory in int a[N]; int main(){}, and heap in int main(){std::vector<int> v(N);}, and, because of that, received different results.
Use heap for big arrays (via the std::vector or the operator new, examples are given above).
The problem is that your array is actually very big. Assuming that int is 4 bytes, 10 000 000 integers will be 40 000 000bytes which is about 40 Mb. In windows maximum stack size is 1Mb and on modern Linux 8Mb. As local variables are located in stack so youre allocating your 40mb array in 1mb or 8mb stack (if youre in windows or linux respectively). So your program runs out of stack space. In case of global array its ok, because global variables are located in bss(data) segment of program which has static size and is not changing. And in case of std::vector your array is allocated in dynamic memory e.g. in heap, thats why your program is not crashing. If you don't want to use std::vector you can dynamically allocate an array on heap like following
int* arrayPtr = new int[N]
Then you need to free unused dynamically allocated memory with delete operator:
delete arrayPtr;
But in this case you need to know how to work with pointers. Or if you want it to not be dynamic and be only in main, you can make your array in main static (I think 99.9% this will work 😅 and I think you need to try) like this
int main() {static int arr[N];return 0;}
Which will be located in data segment (like global variable)

How Dynamic memory allocation allocates memory during run time ?

int a[10];
The above code will create a array of four int variable sizes & thus the programme will be able to store only 4 integers.
Now consider the following commands
int *a,*b,*c,*d;
a= (int *)malloc(sizeof(int));
b= (int *)malloc(sizeof(int));
c= (int *)malloc(sizeof(int));
d= (int *)malloc(sizeof(int));
The above part of code will create four int type pointer & will allocate them memory of int size.
I learnt that dynamic memory allocation allocates memory at rum time.
I want to know that irrespective of using array or malloc(dynamic memory allocation), the user will be getting only four int sized space to store.If we rule out that it is a pointer variable with int size memory, then what will be the use of dynamic memory allocation.In both cases , the user will get only four int spaces & to get more he will need to access the source code.So why do we use malloc or dynamic memory allocation ?
Consider
int a,*b;
cin >> a;
b= (int *)malloc(a*sizeof(int));
The user types a number a and gets a ints. The number a is not known to either to programmer or the compiler here.
As pointed out in the comments, this is still bad style in C++, use std::vector if possible. Even new is still better than malloc. But i hope the (bad) example helps to clarify the basic idea behind dynamic memory allocation.
You're right that it's all just memory. But there is a difference in usage.
In the general case, you don't necessarily know ahead of time the amount of memory you will need and then time when such memory can be safely released. malloc and its friends are written so that they can keep track of memory used this way.
But in many special cases, you happen to know ahead of time how much memory you will need and when you will stop needing it. For example, you know you need a single integer to act as a loop counter when running a simple loop and you'll be done with it once the loop has finished executing. While malloc and its friends can still work for you here, local variables are simpler, less error prone and will likely be more efficient.
int a[10];
The above line of code will allocate an array of 10 int's of automatic storage duration, if it was within a local scope.
int *a,*b,*c,*d;
The above, however, will allocate 4 pointers to int also of automatic storage duration, likewise if it was within a local scope.
a= (int *)malloc(sizeof(int));
b= (int *)malloc(sizeof(int));
c= (int *)malloc(sizeof(int));
d= (int *)malloc(sizeof(int));
And finally, the above will allocate int variable per each pointer dynamically. So, every pointer of the above will be pointing to a single int variable.
Do note that dynamically allocated memory can be freed and resized at runtime unlike static memory allocation. Memory of automatic storage duration are freed when run out of scope, but cannot be resized.
If you program in C, casting the result of malloc is unnecessary.
I suggest you to read this: Do I cast the result of malloc?
Then what your doing in your code with the 4 pointers is unnecessary; in fact you can just allocate an array of 4 int with one malloc:
int *a;
a = malloc(4 * sizeof(int));

how many elements in dynamically allocated class array

I have a simple class called tire. Now I want to dynamically allocate the number of tires for a vehicle when a vehicle object is created. For this, I want to create an array of tire-class objects with size equal to the number of tires. To check my code, I would like to print the number of objects in the tire-class array.
The question is: Is there a function which can check how many elements are in my tire class array? Can I use the sizeof() function?
Here is the code:
#include <iostream>
// create a class for the tires:
class TireClass {
public:
float * profileDepths;
};
// create class for the vehicle
class vehicle {
public:
int numberOfTires;
TireClass * tires;
int allocateTires();
};
// method to allocate array of tire-objects
int vehicle::allocateTires() {
tires = new TireClass[numberOfTires];
return 0;
};
// main function
int main() {
vehicle audi;
audi.numberOfTires = 4;
audi.allocateTires();
// check if the correct number of tires has been allocated
printf("The car has %d tires.", sizeof(audi.tires));
// free space
delete [] audi.tires;
return 0;
};
No, there's none. Consider using std::vector. Or just store tires count in some other variable (maybe numberOfTires is good enough?).
Well, what happens when you run the code? Does it change if you compile in 32 or 64 bit mode, if you have the facility?
What's happening is that you're asking the compiler to tell you the storage size (in bytes) needed to hold the tires variable. This variable has type TyreClass*, so the storage size is that needed for a data pointer: this might be anything, but today it will probably be 4 bytes for a 32-bit system, or 8 bytes for a 64-bit system.
Whilst it's possible to use sizeof to tell you the size of a statically allocated array, it's not possible for dynamic (heap) allocation. The sizeof operator (in C++, at least) works at compile time, whereas dynamically allocating memory is done when your programme runs.
Much better, for all sorts of reasons, would be to use a std::vector<TyreClass> to hold your tyres. You can then easily get the number of tyres stored, and don't have to worry about allocating or deallocating arrays yourself.
(EDIT: Gah, forgive me mixing up english/american spellings of tyre/tire. It's late and I'm tyred.)

Stack overflow when declare 2 array

When I run my program with 1 array, like this:
int a[430][430];
int i, j, i_r0, j_r0;
double c, param1, param2;
int w_far = 0,h_far = 0;
char* magic_num1 = "";
it's good!
But, when I write:
int a[430][430];
int i, j, i_r0, j_r0;
int nicky[430][430]; // Added line
double c, param1, param2;
int w_far = 0,h_far = 0;
char* magic_num1 = "";
the program not run with the error: "stack overflow"!
I don't know how to solve it!
You need to either increase the stack space (how that is done depends on your platform), or you need to allocate the array from the heap, or even better, use std::vector instead of an array.
You're trying to allocate ~1.48 MB of stuff on the stack1, on your system (and not only on it) that's too much.
In general, the stack is not made for keeping big objects, you should put them in the heap instead; use dynamic allocation with new or std::vector, or, even better suited in your case, boost::multi_array.
1. Assuming 32 bit ints.
A proper solution is to use heap, but also note that you'll likely find that changing to:
short a[430][430];
short nicky[430][430]; // Added line
fixes the overflow, depending on your platform. So if 'short', or 'unsigned short' is big enough, this might be an option.
In fact, even when using the heap, consider carefully the array type to reduce memory footprint for a large array.
Local variables are allocated to "stack", which is a storage space used to several purposes and limited to a certain size.
Usually you can declare variables up to several kilobytes, but when you want to use more memory, usually suggested to use "heap", which can be allocated by new operator or std::vector.
std::vector is an alternate for traditional arrays, and its data is safely stored in heap.
To avoid stack overflow, allocate the arrays in the heap.
If one uses C, then allocating an array of size n in the heap can be done by e.g.
int* A = (int*) malloc(n*sizeof(int));
But you must remeber to free that memory when no longer needed with
free(A);
to avoid memory leak.
Equivalently in C++:
int* A = new int[n];
and free with
delete [] A;
This site was helpful.

Dynamic Function Memory? C++

I've been reading through some books, and when it comes to Class/Functions using Pointers/Dynamic Memory (or heap or w/e they call it) I start to get confused.
Does anyone have a simple....like easy example they can show, because the books im using are using overly complex examples (large classes or multiple functions) and it makes it hard to follow. Pointers have always been my weak point anyways but I understand BASIC pointers, just classes/functions using them is a little bit confusing.
Also.....when would you use them is another question.
Stack allocation:
char buffer[1000];
Here the 1000 must be a constant. Memory is automatically freed when buffer goes out of scope.
Heap Allocation:
int bufsz = 1000;
char* buffer = new char[bufsz];
//...
delete [] buffer;
Here bufsz can be a variable. Memory must be freed explicitly.
When to use heap:
You don't know how much space you will need at compile time.
You want the memory/object to persist beyond the current scope.
You need a large chunk of memory (stack space is more limited than heap space)
Your computer's RAM is a big pile of bytes ordered one after another, and each one of those bytes can be accesed independently by it's address: an integer number startig from zero, upwards. A pointer is just a variable to hold that address of a single place in memory.
Since the RAM is a big chunk of bytes, the CPU ussually divides that big pile of bytes on several chunks. The most important ones are:
Code
Heap
Stack
The Code chunk is where the Assembly code lies. The Heap is a big pool of bytes used to allocate:
Global variables
Dynamic data, via the new operation on C++, or malloc() on C.
The stack is the chunk of memory that gets used to store:
Local variables
Function parameters
Return values (return statement on C/C++).
The main difference between the Stack and Heap is the way it is used. While the Heap is a big pool of bytes, the Stack "grows" like a stack of dishes: you can't remove the dish on the bottom unless there are no more dishes on it's top.
That's how recursion is implemented: every time you call a function recursively, memory grows on the stack, allocating parameters, local variables and storing return values of the returning functions, one on top of the others just like the stack of dishes.
Data living on the Stack have different "Life Span" than the data living on the Heap. Once a function exits, the data on the local variables get lost.
But if you allocate data on the Heap, that data won't get lost util you explicitly free that data with the delete or free() operations.
A pointer is basically a variable that contains the memory address of another variable (or in other cases to a function, but lets focus on the first).
That means that if I declare int[] x = {5,32,82,45,-7,0,123,8}; that variable will be allocated to memory at a certain address, lets say it got allocated on address 0x00000100 through 0x0000011F however we could have a variable which indicates a certain memory address and we can use that to access it.
So, our array looks like this
Address Contents
0x00000100 1
0x00000104 32
0x00000108 82
0x0000010B 45
0x00000110 -7
0x00000114 0
0x00000118 123
0x0000011B 8
If, for example, we were to create a pointer to the start of the array we could do this: int* p = &x; imagine this pointer variable got created a memory address 0x00000120 that way the memory at that address would contain the memory location for the start of array x.
Address Contents
0x00000120 0x00000100
You could then access the contents at that address through your pointer by dereferencing the pointer so that int y = *p would result in y = 1. We can also move the pointer, if we were to do p += 3; the pointer would be moved 3 addresses forward (note, however, that it moves 3 times the size of the type of object it is pointing to, here I am making examples with a 32 bit system in which an int is 32 bits or 4 bytes long, therefore the address would move by 4 bytes for each increment or 12 bytes in total so the pointer would end up pointing to 0x0000010B), if we were to dereference p again by doing y = *p; then we'd end up having y = 45. This is just the beginning, you can do a lot of things with pointers.
One of the other major uses is to pass a pointer as a parameter to a function so that it can do operations on certain values in memory without having to copy all of them over or make changes that will persist outside of the function's scope.
Warning: Don't do this. This is why we have vectors.
If you wanted to create an array of data, and return if from a function, how would you do it?
Obviously, this does not work:
int [10] makeArray(int val)
{
int arr[10];
for(int i=0; i<10; ++i)
arr[i] = val;
return arr;
}
You cannot return an array from a function. We can use pointers to refer to the first element of an array, like this:
int * makeArray(int val)
{
int arr[10];
for(int i=0; i<10; ++i)
arr[i] = val;
return &(arr[0]); // Return the address of the first element.
// Not strictly necessary, but I don't want to confuse.
}
This, however, also fails. arr is a local variable, it goes on the stack. When the function returns, the data is no longer valid, and now you have a pointer pointing to invalid data.
What we need to do is declare an array that will survive even after the function exits. For that, we use keyword new which creates that array, and returns the address to us, which needs to be stored in a pointer.
int * makeArray(int val)
{
int * arr = new int[10];
for(int i=0; i<10; ++i)
arr[i] = val;
return arr;
}
Then you can call that function and use that array like this:
int * a = makeArray(7);
for(int i=0; i<10; ++i)
std::cout << a[i] << std::endl;
delete [] a; // never forget this. Obviously you wouldn't do it right
// away like this, but you need to do it sometime.
Using pointers with new also gives you the advantage that you can determine the size of the array at runtime, something you can't do with local static arrays(though you can in C):
int * makeArray(int size, int val)
{
int * arr = new int[size];
for(int i=0; i<size; ++i)
arr[i] = val;
return arr;
}
That used to be one of the primary purposes for pointers. But like I said at the top, we don't do that anymore. We use vector.
One of the last vestiges of pointers is not for dynamic arrays. The only time I ever use them, is in classes where I want one object to have access to another object, without giving it ownership of that object. So, Object A needs to know about Object B, but even when Object A is gone, that doesn't affect Object B. You can also use references for this, but not if you need to give Object A the option to change which object it has access to.
(not tested, just writing down. and keeping things intentionally primitive, as requested.)
int* oneInt = new int; // allocate
*oneInt = 10; // use: assign a value
cout << *oneInt << endl; // use: retrieve (and print) the value
delete oneInt; // free the memory
now an array of ints:
int* tenInts = new int[10]; // allocate (consecutive) memory for 10 ints
tenInts[0] = 4353; // use: assign a value to the first entry in the array.
tenInts[1] = 5756; // ditto for second entry
//... do more stuff with the ints
delete [] tenInts; // free the memory
now with classes/objects:
MyClass* object = new MyClass(); // allocate memory and call class constructor
object->memberFunction("test"); // call a member function of the object
delete object; // free the object, calling the destructor
Is that what you wanted? I hope it helps.
I think this is what you're asking about:
Basically C++ doesn't allow variable-sized arrays. Any array in C++ has to be given a very specific size. But you can use pointers to work around that. Consider the following code:
int *arry = new int[10];
That just created an array of ints with 10 elements, and is pretty much the same exact thing as this:
int arry[] = int[10];
The only difference is that each one will use a different set of syntax. However imagine trying to do this:
Class class:
{
public:
void initArry(int size);
private:
int arry[];
};
void class::initArry(int size)
{
arry = int[size]; // bad code
}
For whatever reason C++ was designed to not allow regular arrays to be assigned sizes that are determined at runtime. Instead they have to be assigned sizes upon being coded. However the other way to make an array in C++ - using pointers - does not have this problem:
Class class:
{
public:
~class();
void initArry(int size);
private:
int *arry;
};
class::~class()
{
delete []arry;
}
void class::initArry(int size)
{
arry = new int[size]; // good code
}
You have to do some memory cleanup in the second example, hence why I included the destructor, but by using pointers that way you can size the array at runtime (with a variable size). This is called a dynamic array, and it is said that memory here is allocated dynamically. The other kind is a static array.
As far as 2-dimensional arrays go, you can handle it kind of like this:
Class class:
{
public:
~class();
void initArrays(int size1, int size2);
private:
int **arry;
};
class::~class()
{
delete [] arry[0];
delete [] arry[1];
delete [] arry;
}
void class::initArrays(int size1, int size2)
{
arry = new int*[2];
arry[0] = new int[size1];
arry[1] = new int[size2];
}
Disclaimer though: I haven't done much with this language in a while, so I may be slightly incorrect on some of the syntax.