Stack overflow C++ - c++

This is my code. When I access dtr array in initImg function it gives a stack overflow exception. What might be the reason?
#define W 1000
#define H 1000
#define MAX 100000
void initImg(int img[], float dtr[])
{
for(int i=0;i<W;i++)
for(int j=0;j<H;j++)
img[i*W+j]=255;
for(int j=0;j<H;j++)
{
img[j] = 0;
img[W*(W-1)+j] = 0;
}
for(int i=0;i<W;i++)
{
img[i*W] = 0;
img[i*W+H-1] = 0;
}
for(int i=0;i<W;i++)
for(int j=0;j<H;j++)
{
if(img[i*W+j]==0)
dtr[i*W+j] = 0; // <------here
else
dtr[i*W+j] = MAX; // <------here
}
}
int main()
{
int image[W*H];
float dtr[W*H];
initImg(image,dtr);
return 0;
}

This:
int image[W*H];
float dtr[W*H];
Creates each a 4 * 1000 * 1000 ~ 4 MB array into the stack. The stack space is limited, and usually it's less than 4 MB. Don't do that, create the arrays in the heap using new.
int *image = new int[W*H];
float *dtr = new float[W*H];

Your stack probably isn't big enough to hold a million ints and a million floats (8MB). So as soon as you try to access beyond your stack size, your operating system throws you an error. Objects or arrays above a certain size need to be allocated on the heap - preferably using a self-managing self-bounds-checking class such as std::vector - the specific size depends on your implementation.

In addition to the stack overrun, you have another problem -- one which is masked by your definitions of W and H.
for(int i=0;i<W;i++)
for(int j=0;j<H;j++)
{
if(img[i*W+j]==0)
dtr[i*W+j] = 0; // <------here
else
dtr[i*W+j] = MAX; // <------here
}
Your i loop should count from 0 to H-1, rather than W-1 (and the j loop should swap as well). Otherwise your code will only work correctly if W==H. If WH you will overrun your buffers.
This same problem exists elsewhere in your code sample as well.

You're creating giant arrays on the stack. Just use std::vector instead:
std::vector<int> image(W*H);
std::vector<float> dtr(W*H);

Your stack is full. You can allocate memory in heap or increase the stack memory. From what I know the maximum size is about 8MB, but this is not a very good idea. The best solution is to use heap allocation or some containers (vector) available in std.

You will eventually get to
dtr[W*W+j] = 0;   <------here
Which is much more than you have allocated.

Your compiler will define the stack size. A way to get around this is to dynamically allocate your arrays using std::vector array_one(W*H).

You are trying to allocate memory from stack. the maximum memory which can be allocated using stack is complier dependent.
So try something like this to avoid this kind of exception.
#include <stdlib.h>
#define W 1000
#define H 1000
#define MAX 100000
void initImg(int img[], float dtr[])
{
for(int i=0;i<W;i++)
for(int j=0;j<H;j++)
img[i*W+j]=255;
for(int j=0;j<H;j++)
{
img[j] = 0;
img[W*(W-1)+j] = 0;
}
for(int i=0;i<W;i++)
{
img[i*W] = 0;
img[i*W+H-1] = 0;
}
for(int i=0;i<W;i++)
for(int j=0;j<H;j++)
{
if(img[i*W+j]==0)
dtr[i*W+j] = 0; // <------here
else
dtr[i*W+j] = MAX; // <------here
}
}
int main()
{
int *image = (int*)malloc(4*W*H); //Malloc the memory....(Allocated from Heap..)
float *dtr = (float*)malloc(4*W*H);
if(image && dtr) //If none of the ptr is NULL. Means memory is allocated...
{
initImg(image,dtr);
}
return 0;
}
You can use new as well instead of using malloc to allocate memory from heap...

Related

Check memory usage of radixsort C++

I have implemented radix sort in c++
...
void *countSort(int *tab, int size, int exp, string *comp, bool *stat) {
int output[size];
int i, index, count[10] = {0};
sysinfo(&amem);
for (i = 0; i < size; i++){
index = (tab[i]/exp)%10;
count[index]++;
}
for (i = 1; i < 10; i++)
count[i] += count[i - 1];
for (i = size - 1; i >= 0; i--) {
index = count[ (tab[i]/exp)%10 ] - 1;
output[index] = tab[i];
count[ (tab[i]/exp)%10 ]--;
}
if((*comp).rfind("<",0) == 0){
for (i = 0; i < size; i++){
tab[i] = output[i];
swap_counter++;
if(!*stat){ fprintf(stderr, "przestawiam\n"); }
}
}else{
for (i = 0; i < size; i++){
tab[i] = output[size-i-1];
swap_counter++;
if(!*stat){ fprintf(stderr, "przestawiam\n"); }
}
}
}
void *radix_sort(int size, int *tab, string *comp, bool *stat) {
int m;
auto max = [tab, size](){
int m = tab[0];
for (int i = 1; i < size; i++) {
if (tab[i] > m)
m = tab[i];
}
return m;
};
m = max();
for (int exp = 1; m/exp > 0; exp *= 10)
countSort(tab, size, exp, comp, stat);
}
...
int main(){
int tab = (int *) malloc(n*sizeof(int));
for(int n = 100; n <=10000; n+=100){
generate_random_tab(tab, n);
radix_sort(sorted_tab, 0, n-1, ">=", 1);
free(tab);
}
}
Now I want to check and print out information of how much memory radix sort uses.
I want to do this to compare how much of memory different sorting algorithms uses.
How to achieve this?
I was given a hint to use a sysinfo() to analyze how system memory usage changes but I couldn't achieve constant results.
(I'm working on linux)
Your program has linear memory usage malloc(n*sizeof(int)) and int output[size]; --- one of them on heap, the other on stack, so basically you don't need to make run-time measurements as you can calculate it easily.
As you are on Linux, for more complicated cases there is e.g. massif tool in valgrind, but it is focused on heap measurements (which in normal cases in which you want to measure memory usage is enough, as stack is usually to small for serious amounts of data).
sysinfo only shows whole system memory, not individual process memory.
For process memory usage, you might try mallinfo, e.g.
struct mallinfo before = mallinfo();
// radix sort code
struct mallinfo after = mallinfo();
Now you may compare the various entries before and after your sorting code.
Be aware, that this doesn't include stack memory.
Although I don't know, how accurate these numbers are in a C++ context.
Testing a complete example
#include <malloc.h>
#include <stdio.h>
#define SHOW(m) printf(#m "=%d-%d\n", after.m, before.m)
int main()
{
struct mallinfo before = mallinfo();
void *p1 = malloc(1000000);
//int *p2 = new int[1000000];
struct mallinfo after = mallinfo();
SHOW(arena);
SHOW(ordblks);
SHOW(smblks);
SHOW(hblks);
SHOW(hblkhd);
SHOW(usmblks);
SHOW(fsmblks);
SHOW(uordblks);
SHOW(fordblks);
SHOW(keepcost);
return 0;
}
shows different values, depending on whether you use malloc
arena=135168-0
ordblks=1-1
smblks=0-0
hblks=1-0
hblkhd=1003520-0
usmblks=0-0
fsmblks=0-0
uordblks=656-0
fordblks=134512-0
keepcost=134512-0
or new
arena=135168-135168
ordblks=1-1
smblks=0-0
hblks=1-0
hblkhd=4001792-0
usmblks=0-0
fsmblks=0-0
uordblks=73376-73376
fordblks=61792-61792
keepcost=61792-61792
It looks like C++ (Ubuntu, GCC 9.2.1) does some preallocation, but the relevant number seems to be hblkhd (on my machine).
Since your only dynamic allocation is at the beginning of main, you must do the first mallinfo there. Testing only the radix sort code reveals, that there are no additional dynamic memory allocations.

c++ delete[] 2d array caused Heap Corruption

When I tried to delete a 2-D array in C++ , it caused an error in Visual Studio 2017:
HEAP CORRUPTION DETECTED: after Normal block (#530965) at 0x0ACDF348.
CRT detected that the application wrote to memory after end of heap buffer.
The code is below:
const int width = 5;
const int height = 5;
bool** map = new bool*[height];
for (int i = height; i >= 0; --i) {
map[i] = new bool[width];
}
for (int i = height; i >= 0; --i) {
delete[] map[i];
}
delete[] map; // error occurs here
What's wrong with the code please?
You're getting out of the bound of the array; which leads to UB. Note that the range is [0, height), the elements are numbered 0, …, height - 1.
Change the two for loop from
for (int i = height; i >= 0; --i) {
to
for (int i = height - 1; i >= 0; --i) {
PS: In most cases we don't need to use raw pointers and new / delete expression manually, you can just use array (not with raw pointer), or std::vector and std::array, or smart pointers instead.

Thread 1: EXC_BAD_ACCESS (code 1) error

When I run this short program, I generate the error "Thread 1: EXC_BAD_ACCESS (code 1)". Can anyone help me determine the cause of the problem?
//populates matrix with rand nums
void popMat(int x[][4096]){
for(int i = 0; i < 4096; i++){
for(int j = 0; j < 4096; j++){
x[i][j] = rand() % 100;
}
}
return;
}
int main(int argc, char * argv[]) {
int mat1 [4096][4096];
int mat2 [4096][4096];
popMat(mat1);
popMat(mat2);
for(int i = 0; i < 4096; i++){
for(int h = 0; h < 4096; h++){
printf("%d, %d\n", i, h);
}
}
return 0;
}
Assuming 4 bytes integer, int mat1 [4096][4096]; requires 64MB of memory. Two such arrays require 128 MB of memories. On most systems stack memory, where local variables are created, is not capable of storing such large memory and you are getting a stack overflow.
One easy solution is to move the array is global scope(using global is not much recommended). Another solution is to allocate these arrays dynamically with malloc or new. Another solution is to use std::vector instead of statically allocated C arrays.
PS:
Do not forget to free memory if you decide to allocate them dynamically.
Even after you fix this issue you will see that rand() is always generating same values as srand() is not called.

C++ 2D Array Allocating Memory to Avoid Segmentation Fault

I usually code in other languages (R, Python and Java), but recently started using C++. I've been solving problems on hackerrank.com, and specifically I bumped into this one:
https://www.hackerrank.com/challenges/variable-sized-arrays
Prior to this question, I had never gotten a Segmentation Fault error. I've tinkered with the code and discovered that the error only occurs when I attempt to print from the arr variable.
I wonder if someone could help me with this, and maybe provide a detailed explanation as to the precise error?
The code is as follows, but the issue is likely with int arr[100000][100000] = {-1}; and printf("%d\n", arr[iHat][jHat]); because I can printf both iHat and jHat themselves, but I am unable to use them to access integers in the arr array.
#include <iostream>
using namespace std;
int main(){
int n, q;
/*
*scan in:
*n array entries
*q quaries
*/
int arr[100000][100000] = {-1}; //initialize an array, larger than 10^5
scanf("%d %d\n", &n, &q); //n is size of array, q is # of quaries
for (int i = 0; i < n; ++i){ //loop through lines of input to populate array
int c, y = 0; //initialize to zero at the start of each line
while((c = getchar()) != '\n'){ //readline
if(c != ' '){ //pass spaces
arr[i][y] = c; //place integer into array
++y;
}
}
}
for (int i = 0; i < q; ++i){
int iHat, jHat = 0;
scanf("%d %d\n", &iHat, &jHat); //scan for coordinates
printf("%d\n", arr[iHat][jHat]); //Segmentation fault occurs here, why?
}
return 0;
}
Update
This question focused on memory management, and in particular the use of pointers. A functioning solution, resulting in no segmentation faults, is as follows:
#include <iostream>
using namespace std;
int main(){
int n, q;
/*
*scan in:
*n array entries
*q quaries
* format: %d %d
*/
scanf("%d %d\n", &n, &q);//n is size of array of arrays, q is # of quaries
int **arr = new int *[n]; //int** arr is a pointer of pointers of size n
for (int i = 0; i < n; ++i){//loop through lines of input to populate array
int k; //Always initialize variables in the narrowest scope possible!
scanf("%d", &k);//grab k, the number of ints in the line
arr[i] = new int[k];//create a 2nd dimension at entry i of size k
for (int j = 0; j < k; ++j){
scanf("%d", &arr[i][j]);//populate array
}
}
for (int i = 0; i < q; ++i){
int iHat, jHat = 0;
scanf("%d %d\n", &iHat, &jHat); //scan for query coordinates
printf("%d\n", arr[iHat][jHat]); //print results of query
}
return 0;
}
C++ gives you control of where you want to allocate memory. In your case, what you have found is that you allocated an array-of-array-of-int on the stack which exceeds the stack size. At some point, you access one of these elements which lies outside the bounds of the stack and also the program, which causes an access violation called a segmentation fault.
Since you mentioned being new to C++, it would help to understand these 3 areas of memory and how you would use each for your case:
Stack memory - space for temporary variables to automatically use without having to explicitly request. You will see undefined behavior if you exceed the stack size.
int main() {
int arr[100000][100000];
}
Heap memory - space for dynamically allocating space whenever explicitly requested using the operator "new". An "std::bad_alloc" exception will be thrown if the requested memory size exceeds what is available.
int main() {
int **arr = new int *[100000];
for (std::size_t i = 0; i < 100000; ++i) {
arr[i] = new int[100000];
}
}
Static memory - space allocated for static objects before main runs. You will get a compiler error if the array dimensions are too large.
int arr[100000][100000];
int main() {
...
}
That's 40 GB!
Even if you have that much RAM in the machine, it is surely not allocated as stack space.
If you do have that much memory you can move the arr to the global area before main. That way it will not be on the stack.
If you don't have 40+ GB available, you might have to rethink the solution. :-) Perhaps do the calculations in smaller segments?
Here are a few thoughts
1) You are trying to allocate 100,000 x 100,000 bytes, which equal 10,000,000,000 bytes (~10GB) on the stack. The default stack size is about 8MB on 32-bit linux. Even if the stack size is larger it won't be 10GB.
2) The name of the exercise you were working on is "Variable Sized Array" The line you entered,int arr[100000][100000] is a fixed size array. You should be using keyword new to dynamically create the array.
3) The reason for the Segmentation Fault error is because your print statement is attempting to access memory outside of the Virtual Memory space allowed for a stack size.
[Suggestion]
1) trying doing some exercises where you allocate and clean up dynamic memory using new and delete. Also in C++ allocating and deleting arrays is done differently than just a single data structure.
Cheers
Are you trying to do this?
#include <iostream>
using namespace std;
int main(){
int n, q;
const int length = 100;
int arr[length][length] = { -1 };
cout << "Enter length of 2d array" << endl;
cin>>n>>q;
cout << "Fill the array" << endl;
for (int i = 0; i < n; ++i) {
for(int y=0;y<q;y++){
int f;
cin >> f;
arr[i][y]=f;
}
}
int iHat;
int jHat;
cout << "Enter coordinates" << endl;
cin>>iHat>>jHat;
cout<<arr[iHat][jHat];
return 0;
}
P.S i decreased array size, becouse 100000 x 100000 this is lot of gigabytes and it says array is too large

How to add contiguous blocks of memory (dynamically) to a previosly allocated dynamic memory

I am working with Arduino. My main task is to divide the entire room into small grids and do a mapping of the obstacles in the room using ultrasonic sensors.
For that i wish to allocate memory dynamically. Now these sensors can detect only up to 4m. So i will divide that distance into blocks and allocate memory. But as the robo moves ahead it will discover more room and needs more memory appended to the previously allocated memory.
So this is a question of adding contiguous block of memory to a previously allocated memory.
This is a small part of the code that is related to the problem.
//max_x and max_y are the number of blocks in x and y direction respectively.
int **grid = new *int[max_x];
for(int i = 0; i <max_x; i++)
{
int grid[i] = new int[max_y];
}
void foo(); //stores some values in the previously allocated memory.
dist_y = get_y(); //returns blocks available in y direction.
dist_x = get_x(); //returns blocks available in x direction.
if((dist_y > max_y) | (dist_x > max_x))
{
append_grid((max_x-dist_x),(max_y-dist_y)); //add these many number of blocks.
}
So how to add more memory depending on the distance measured?
I think this is what you are trying to do
#include <iostream>
using namespace std;
int max_x=10;
int max_y=12;
int** changeXY( int** g, int newX, int newY ){
int** temp = new int*[newY];
for(int i = 0; i < newY; i++)
temp[i] = new int[newX];
for( int y = 0; y < max_y; y++)
for( int x = 0; x < max_x; x++)
temp[x][y] = g[x][y];
delete[] g;
return temp;
}
int main() {
//Its easier to think about what you are creating as a vector
//full of vectors rather than a grid. Here you are creating a
//pointer to a string of pointers of size max_y
//or assigning the number of columns
int **grid = new int*[max_y];
//here you are making a loop to add elements to the pointer
//array you just created. if the pointer syntax is confusing remember
//that "grid[i]" is equivalent to "*(grid + i)"
for(int i = 0; i < max_y; i++)
grid[i] = new int[max_x];
grid = changeXY(grid,22,20);
delete[] grid;
return 0;
}
There were a couple mistakes in your syntax. First of all, when you declare a dynamic memory, the syntax is "new int*[max_y]", you are effectively telling the compiler what type to specify. Second, when adding the other dimension in the loop, you are adding it to the grid. Not the first dimension.
OH, btw! the way I wrote this, there is no handling and unless max_y and max_x are global like they are in this example the changeXY() function will have to also include them in the input parameters. Hope this helps.
Now that i am aware of std::vector i think i can use it for this problem. I haven't posted the entire code because I think it will add to too much of details that are not relevant.
vector<vector<int> > grid;
dist_y = get_y(); //returns the number of blocks in Y direction
if(dist_y > threshold){
forward(); //moves a step forward.
dist_x = get_x(); //returns blocks available in X direction.
vector<int> col;
for(int i = 0; i < dist_x; i++) {
col.push_back(1); //1 indicates there is free space there.
}
grid.push_back(col);
}
Repeating this loop will keep adding elements as required.