Thread 1: EXC_BAD_ACCESS (code 1) error - c++

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.

Related

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

C++ : EXC_BAD_ACCESS at basic for loop

int main(int argc, const char * argv[]) {
int N,M;
std::cin >> N;
std::cin >> M;
bool member[N];
for (int i= 0; i < N ; i++) {
member[i] = false;
}
int test[M][N];
int testSize[M];
/*//std::fill_n(testSize, M, 0);
for (int i = 0; i < M; i++) {
std::fill_n(test[M], N, -1);
}*/
for (int i = 0; i < M; i++) {
for (int j = 0; j < N ; j++) {
test[i][j] = -1;
}
testSize[i] = 0;
}
}
This is my c++ code above, that is simple code, isn't it?
But When the program got M as 100000 and N as 1000, there is EXC_BAD_ACCESS at second for loop.
I do not know why it is happening.
When smalle size data is put into, there is no error, but This case made it an error.
I'm solving an algorithm problem and confronting unknowing error.
Is there any point to fix at my program?
As you see my code, what I want is to initialize the array test and testSize to the same value; -1 and 0.
int test[M][N]; allocates an array of M*N elements on the stack. When M == 100000 and N==1000 it is an array of 100 million elements. int is usually at least 4 bytes, so you are trying to allocate 400MB array on a stack, which won't fit with default (or probably any at all) linker settings.
What you can do is to allocate that much memory on heap using malloc or new[]. You can also use 3rd-party classes for operating matrices that will do it for you.

Wrong use of memset?

Can someone please explain what is wrong here:
class test
{
public:
char char_arr[100];
};
int main()
{
test **tq = (test**)calloc(10, sizeof(test*));
for(unsigned int i = 0; i < 10; i++)
tq[i] = (test*)calloc(10, sizeof(test));
for(unsigned int i = 0; i < 10; i++)
memset(tq, 0, sizeof(tq[0][0])*100);
return 0;
}
The code above produces random crashes. The errors are: "memory could not be written", "memory could not be read", "stack is corrupted"
test **tq = (test**)calloc(10, sizeof(test*));
...
for(unsigned int i = 0; i < 10; i++)
memset(tq, 0, sizeof(tq[0][0])*100);
When you allocate tq, you ask for 10 * sizeof(test*) bytes. But when you call memset, you ask it to set sizeof(tq[0][0]*100) bytes. You are definitely writing to more bytes then you allocated. Perhaps you meant:
for(unsigned int i = 0; i < 10; i++)
memset(tq[i], 0, 10 * sizeof(test));
This makes sense because:
tq[i] = (test*)calloc(10, sizeof(test));
When you allocated tq[i], you allocated 10 * sizeof(test) bytes.
You are confusing this for a 2D array:
char x[10][10];
This is a 2D array, which holds 100 contiguous chars.
But you have allocated a bunch of pointers, then pointed them to separate arrays of 10 chars each. The result is not contiguous; you cannot access it in the way you have.

cpp two dimensional dynamic array

I'm using c++ and I want to use two dimensional dynamic array. I tried this:
#include<iostream.h>
using namespace std;
void main(){
int const w=2;
int size;
cout<<"enter number of vertex:\n";
cin>>size;
int a[size][w];
for(int i=0; i<size; i++)
for(int j=0; j<w; j++){
cin>>a[i][j];
}
}
but not worded.
and I tried this:
int *a = new a[size][w];
instead of
int a[size][w];
but not worked!
could you help me plz.
thanks a lot.
The correct approach here would be to encapsulate some of the standard containers, that will manage memory for you, inside a class that provides a good interface. The common approach there would be an overload of operator() taking two arguments that determine the row and column in the matrix.
That aside, what you are trying to create manually is an array of dynamic size of arrays of constant size 2. With the aid of typedef you can write that in a simple to understand manner:
const int w = 2;
typedef int array2int[w];
int size = some_dynamic_value();
array2int *p = new array2int[size];
Without the typedef, the syntax is a bit more convoluted, but doable:
int (*p)[w] = new int [size][w];
In both cases you would release memory with the same simple statement:
delete [] p;
The difference with the approaches doing double pointers (int **) is that the memory layout of the array is really that of an array of two dimensions, rather than a jump table into multiple separately allocated unidimensional arrays, providing better locality of data. The number of allocations is lower: one allocation vs. size + 1 allocations, reducing the memory fragmentation. It also reduces the potential from memory leaks (a single pointer is allocated, either you leak everything or you don't leak at all).
For a dynamic sized array you must dynamically allocate it. Instead of
int *a = new a[size][w];
Use
int** a = new int*[size];
for(int i = 0; i < size; i++)
a[i] = new int[w];
OP is saying he wants to create a 2 dimensional array where one dimension is already known and constant and the other dimension is dynamic.. Not sure if I got it right but here goes:
int main() {
const int w = 2;
int size = 10;
int* arr[w];
for (int i = 0; i < w; ++i)
arr[i] = new int[size];
//do whatever with arr..
//std::cout<<arr[0][0];
for (int i = 0; i < w; ++i)
for (int j = 0; j < size; ++j)
std::cout<<arr[i][j];
for (int i = 0; i < w; ++i)
delete[] arr[i];
return 0;
}
You can not do that in c++, please read about dynamic memory allocation
the code below should work
int* twoDimentionalArray = new [size*w]

Stack overflow 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...