C++ : EXC_BAD_ACCESS at basic for loop - c++

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.

Related

how to create huge 2D arrays in C++

I am trying to create a huge 2D array in c++ like this :
float array[1000000][3];
I have to store some values in this array which has 3 components. This will be done iteratively by two for loops of 1000 loops.
When I try to run this I get an error :
Segmentation fault
Here is a bit of my code :
int m=0,c=0;
float error;int count=0;
array<array<float, 1000000>, 3> errors;
for(int i=0; i<1000; i++){
for(int j=0; j<1000; j++){
error=distance(j+20,m,c,1000-matrix(1,j));
errors[count][0]=error;
errors[count][1]=m;
errors[count][2]=c;
c++;
count++;
}
m++;
c=0;
}
sort(errors.begin(), errors.end());
cout<<errors[0][0]<<endl<<errors[0][1]<<endl<<errors[0][2]<<endl;
The error continues even after commenting out the sort...
matrix(1,j) is a matrix and I am accessing its elements using this method.
I want minimum value of error and the set of values of m and c for which error is minimum.
Is there any way I can achieve this?
Thanks in advance.
You can use array to easily perform your task. Here what you can:
#include<array>
using namespace std;
Then, let create your data array:
const int N = 1000000;
const int M = 3;
array<array<float, N>, M> my_array;
You can fill this newly created array by doing:
for(int i=0; i < N; i++){
for(int j=0; j < M; j++){
my_array[i][j] = 0.0f; // Just for example
}
}
For more information on how to use array library, please see here
If you don't want to use array, you can also proceed as follows:
const int N = 10000000;
const int M = 3;
float *my_array
my_array = new float[N*M]; // give it a memory on the stack
if(my_array == nullptr){
cerr << "ERROR: Out of memory" << endl;
}
for(int i=0; i < N; i++){
for(int j=0; j < M; j++){
*(my_array + i*N + j) = 0.0f; // Just for example
}
}
Make sure you release the memory you acquired by doing:
delete [] my_array;

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.

Passing integers to arrays within functions (without pointers)

I'm trying to create a magic square that will print four different grid sizes (5x5, 7x7, 9x9, 15x15). The error I'm having is the array magsquare within the function tells me it needs a constant integer. (I can't use pointers) This is a class assignment.
#include <iostream>
#include <iomanip>
using namespace std;
void magicSquare(int n){
int magsquare[n][n] = { 0 }; /*THIS is the error with [n][n]*/
int gridsize = n * n;
int row = 0;
int col = n / 2;
for (int i = 1; i <= gridsize; ++i)
{
magsquare[row][col] = i;
row--;
col++;
if (i%n == 0)
{
row += 2;
--col;
}
else
{
if (col == n)
col -= n;
else if (row < 0)
row += n;
}
}
for (int i = 0; i < n; i++){
for (int j = 0; j < n; j++){
cout << setw(3) << right << magsquare[i][j];
}
cout << endl;
}
}
int main(){
int n = 5;
magicSquare(n);
return 0;
}
Indentation may look incorrect, but it's right. Sorry.
The failure is because standard C++ cannot allocate dynamically sized array on the stack, as you are trying to do.
int magsquare[n][n];
As far as magicSquare is concerned n is only known at runtime and for an array to be allocated on the stack it's size must be known at compile time.
Use a 15 x 15 array.
int magsquare[15][15];
As long as you know this is the largest you'll ever need, you should be ok.
Alternatives (which you've already said you can't use)
Use new to declare a 2d array of the required dimensions. (Remember to delete[] it though)
Use std::vector
It may also be a good idea to add a check that n values over 15 or under 1 are rejected, otherwise you'll face undefined behaviour if any values outside of 1-15 are passed into the function.

Input from keyboard into a 2d dynamic array

So i'm trying to write a function which would get input from keyboard and store it in the 2d dynamic array. n is the number of lines (tried with 1-4 lines), m is the number of characters per line (256 in my case). I've read plenty about dynamic arrays and the use of new and the code seems totaly fine to me, but i keep getting this error when i try to enter the text: Access violation reading location 0x00000000. Can't figure out why. Please help.
void KeyInput (char **string, unsigned int n, unsigned int m)
{
cout<<endl<<"Input from keyboard"<<endl;
string=new char* [n];
for(unsigned int i = 0; i < n; i++ )
string[i]=new char[m];
for(unsigned int i = 0; i < n; i++ )
gets(string[i]);
}
can you give more information on where you are getting the access violation? I tried the following code (Visual Studio 2010, Window 7 Professional) and did not get an error. Note that I did change the characters per line to 15 instead of 255 as I wanted to test boundary conditions without a lot of typing.
Your function seems to work fine on my machine, however you do have a latent buffer-overflow using gets as it does not check for the length of the string. Remember that gets will append a null-terminator for you, so if in your case you enter exactly 255 characters you will overflow your buffer by one.
void KeyInput(char** string, unsigned int n, unsigned int m);
int _tmain(int argc, _TCHAR* argv[])
{
char* strArray;
KeyInput(&strArray, 4, 15);
return 0;
}
void KeyInput(char** string, unsigned int n, unsigned int m)
{
string = new char*[n];
for(unsigned int i = 0; i < n; i++)
{
string[i] = new char[m];
}
for(unsigned int i = 0; i < n; i++)
{
gets(string[i]);
}
}
(also ignore the hideous _tmain and _TCHAR stuff, they are Windows idiosyncrasies :) ).
Finally, unless this is an assignment (or an exercise for self learning), do what 40two suggested and use STL to make your life easy.
Use a vector of strings, take advantage of the force that STL has (use the force Luke see code below how):
void KeyInput (std::vector<std::string>& str_vec, int const n)
{
std::cout << "\nInput from keyboard" << std::endl;
for (auto i = 0; i < n; i++) {
std::string tmp;
std::getline(std::cin, tmp);
str_vec.push_back(tmp);
}
}
Update or Why your C++ teachers are wrong:
void KeyInput(char ***string, unsigned int n, unsigned int m)
{
std::cout << "\nInput from keyboard" << std::endl;
*string = new char*[n];
for (unsigned int i = 0; i < n; i++)
(*string)[i] = new char[m];
for (unsigned int i = 0; i < n; i++)
std::gets((*string)[i]);
}
int main()
{
char **string = 0;
KeyInput(&string, 4, 100);
for (auto i = 0; i < 4; ++i) std::cout << string[i] << std::endl;
return 0;
}
You need triple pointers in order to pass the 2d array by reference and to be properly filled (OMG!!!).
The user can enter only limited length strings (e.g., 99) don't forget strings have one character at the end (i.e., '/0' the null character).
You have to take care of the memory allocated and deleted later in order to avoid memory leaks.
If you want to shoot your self in the foot continue to program like this.

fastest way to set a 2-dim array of double all to -1? [duplicate]

This question already has answers here:
how to use memset for double dimentional array?
(2 answers)
Closed 9 years ago.
What is the fastest way to set a 2-dim array of double,such as double x[N][N] all to -1?
I tried to use memset, but failed. Any good idea?
Use: std::fill_n from algorithm
std::fill_n(*array, sizeof(array) / sizeof (**array), -1 );
Example:
double array[10][10];
std::fill_n( *array, sizeof(array) / sizeof (**array), -1.0 );
//Display Matrix
for(auto i=0;i<10;i++)
{
for(auto j=0;j<10;j++)
cout<<array[i][j]<< " ";
cout<<endl;
}
A simple loop:
#include <stdio.h>
int main(void)
{
#define N 5
double x[N][N];
size_t i, n = sizeof(x) / sizeof(double);
for (i = 0; i < n; i++)
x[0][i] = -1.0;
for (i = 0; i < n; i++)
printf("%zu) %f\n", i, x[0][i]);
}
// create constants
const int rows = 10;
const int columns = 10;
// declare a 2D array
double myArray [rows][columns];
// run a double loop to fill up the array
for (int i = 0; i < rows; i++)
for (int k = 0; k < columns; k++)
myArray[rows][columns] = -1.0;
// print out the results
for (int i = 0; i < rows; i++) {
for (int k = 0; k < columns; k++)
cout << myArray[rows][columns];
cout << endl;
}
Also you can set directly
double x[4][4] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}
if the array index is small.
Using std::array and its fill method:
#include <array>
#include <iostream>
int main()
{
const std::size_t N=4
std::array<double, N*N> arr; // better to keep the memory 1D and access 2D!
arr.fill(-1.);
for(auto element : arr)
std::cout << element << '\n';
}
Using C++ containers you can use the fill method
array<array<double, 1024>, 1024> matrix;
matrix.fill(-1.0);
if, for some reason, you have to stick with C-style arrays you can initialize the first row manually and then memcpy to the other rows. This works regardless if you have defined it as static array or allocated row by row.
const int rows = 1024;
const int cols = 1024;
double matrix[rows][cols]
for ( int i=0; i<cols; ++i)
{
matrix[0][cols] = -1.0;
}
for ( int r=1; r<rows; ++r)
{
// use the previous row as source to have it cache friendly for large matrices
memcpy(&(void*)(matrix[row][0]), &(void*)(matrix[row-1][0]), cols*sizeof(double));
}
But I rather would try to move from C style arrays to the C++ containers than doing that kind of stunt.
memset shouldn't be used here because it is based on void *. So all bytes in are the same. (float) -1 is 0xbf800000 (double 0xbff0000000000000) so not all bytes are the same...
I would use manual filling:
const int m = 1024;
const int n = 1024;
double arr[m][n];
for (size_t i = 0; i < m*n; i++)
arr[i] = -1;
Matrix is like array in memory, so better to have 1 loop, it slightly faster.
Or you can use this:
std::fill_n(arr, m*n, -1);
Not sure which one is faster, but both looks similar. So probably you'll need to make small test to find it out, but as far as I know people usually use one or another. And another thing first one is more C on some compiler it won't work and second is real C++ it and never works on C. So you should choose by the programming language I think :)