how to create huge 2D arrays in C++ - 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;

Related

I am having a bad access issue

I am trying to create a merge function for two array structures in c++ but am coming up with a bad access error that I don't know how to solve. The error comes up when I am trying to swap the element in the smaller array into the larger, merged array. The code doesn't even go through a single iteration. All three of i, j, and k remain at 0. Any help would be greatly appreciated! Here is the code:
struct Array
{
int *A;
int size;
int length;
};
void display(Array arr){
for (int i = 0; i < arr.length; i++)
std::cout << arr.A[i] << std::endl;
}
Array merge(Array arr1, Array arr2){
Array arr3;
arr3.length = arr1.length + arr2.length;
arr3.size = arr1.length + arr2.length;
int i = 0, j =0, k =0;
while(i <arr1.length && j < arr2.length){
if (arr1.A[i] < arr2.A[j])
{
arr3.A[k] = arr1.A[i]; //(The error is displayed here: Thread 1: EXC_BAD_ACCESS (code=1, address=0x28))
k++;
i++;
}
else if (arr2.A[j] < arr1.A[i])
{
arr3.A[k] = arr2.A[j];
k++;
j++;
}
}
for (; i< arr1.length; i++)
{
arr3.A[k]=arr1.A[i];
k++;
}
for (; i< arr2.length; j++)
{
arr3.A[k]=arr2.A[j];
k++;
}
return arr3;
}
int main() {
Array arr1;
arr1.size = 10;
arr1.length = 5;
arr1.A = new int[arr1.size];
arr1.A[0]= 2;
arr1.A[1]= 6;
arr1.A[2]= 10;
arr1.A[3]= 15;
arr1.A[4]= 25;
Array arr2;
arr2.size = 10;
arr2.length = 5;
arr2.A = new int[arr2.size];
arr2.A[0]= 3;
arr2.A[1]= 4;
arr2.A[2]= 7;
arr2.A[3]= 18;
arr2.A[4]= 20;
Array arr3 = merge(arr1, arr2);
display(arr3);
return 0;
}
Your Array arr3 does not allocate any memory for its int *A field. It's natural that it would not work.
Anyway, your implementation of Array is very poor. Don't reimplement arrays unless you have a good reason; use std::vector instead.
If you really need to implement an Array on your own, then learn about encapsulation, make a class with a constructor, and allocate/delete your data (*A) field properly. Remember, using pointers and heap memory without understanding them is a recipe for disaster.
Easy: arr3.A is not initialized. It's a pointer. What does it point to?
Suggestion: learn about dynamic memory allocation.

Error in output of dynamically initialized 2D array

I'm working on a school project written in c++. I am trying to generate an array of rgb colours based on user input, for a program that generates fractals(irrelevant).
I found the need to use a pointer to a 2D array. The pointer has a global scope because it needs to be accessed across multiple files, in multiple functions.
There is no problem with the declaration of the pointer. It is as such:
in "global.h"
int **ptr;
int palette[10][3];
//all the statements like #ifndef GLOBAL_H_INCLUDED, etc are present
in main.cpp
extern int **ptr;
extern int palette[10][3];
void gen_array();
int main()
{
//initialize values of palette
//palette is basically list of colors that the user selects for the
//desired blend of colors to appear on the screen
gen_array();
}
in void gen_array(), in main.cpp
void gen_array()
{
int i=0, size=0, size_arr=0;
//size is a variable helpful in calculating "size_arr", which is the size of the dynamic array to be initialized
while(palette[i][0]!=256)
{ //calculates "size" }
for(int i=0; i<size-1; i++)
{
//to find "size_arr"
}
ptr= new int*[size_arr]();
for(int i = 0; i < size_arr; ++i)
{
ptr[i] = new int[3];
}
//the following piece of code enter's values column-wise into the array
int s=0;
for(int i=0; i<size-1; i++)
{
for(int k=0; k<3; k++)
{
int x=-1, a=0, b=0;
a= palette[i][k] - palette[i+1][k];
b= palette[i][k];
if(a<0)
{
a= -a;
x=1;
}
for(int j=0; j<=a; j++, s++)
{
ptr[i][k] = b;
//cout<<*(*(ptr+i)+k)<<' ';
b= b+ x;
}
b= b-x;
for(int j=a+1; j<=diff[i]; j++, s++)
{
ptr[i][k] = b;
cout<<ptr[i][k]<<' ';
}
cout<<endl;
}
}
//this output's the array that the pointer points to, on the screen
for(int i=0; i<size_arr; i++)
{
for(int j=0; j<3; j++)
{
cout<<ptr[i][j]<<' ';
}
cout<<endl;
}
}
The problem is that, the data is getting generated and inputted in the array correctly [in the second-last for loop], but when outputting it [the last for loop] I'm getting junk values.
The data inputted [the correct values] as obtained from the cout statements [that are now commented] is this [printed column-wise] whereas the O/P given out is this [printed row-wise].
If it is required to be know, "size" (in this case) =2, size_arr=256 and palette[0]={0, 0, 255} and palette[1]={0,255,0}.
Can anybody point out what the problem is, and whether it has something to do with the pointer initialization?
Even without reading all the program code like
for(int j=0; j<=a; j++, s++)
{
ptr[i][k] = b;
//cout<<*(*(ptr+i)+k)<<' ';
b= b+ x;
}
looks clearly wrong. At each iteration you are writing to ptr[i][k] and the loop doesn't change ptr, i or k. This means that it will keep writing to the very same location during the loop.
Look at your int i in the loop you're using to fill int** ptr. If size = 2 then you're never going to advance ptr far enough to fill the array. Consider filling the array like this:
for(int i = 0; i < size_arr; ++i){//for every pixel in the main array
for(int k = 0; k < 3; ++k){//for every subpixel
int my_value = ...;//calculate the value for this entry
*(*(ptr+i)+k) = my_value;//assign
Better yet, use a struct named pixel containing Uint8 r,g,b and allocate as pixel* ptr = new pixel[size] and iterate over pixels and assign ptr[i].r ptr[i].g ptr[i].b

Dynamic 2D Array Initialization

I want to create and initialize a 2D array but the initialization is failed. I encounter "The program has unexpectedly finished." in Qt Creator.
What is wrong?
in .h file
private:
int pop;
int d;
float **uye;
in .cpp file
pop=50;
d=12;
uye = new float*[pop];
for(int i=0; i<d; i++) uye[i] = new float[d];
for(int n=0; n<pop; n++)
{
for(int m=0; m<d; m++)
{
uye[n][m] = (float) n*m;
}
}
The first loop for(int i=0; i<d; i++) should probably be for(int i=0; i<pop; i++). Otherwise, you are only reserving space for 12 elements, but later try to access 50.
Note that having raw pointer members is considered a very bad idea in modern C++, because you need to worry about copying semantics. Better use a flat std::vector<float> and do the 2D to 1D mapping manually, or use a std::vector<std::vector<float> > with convenient access syntax.
I would prefer the second version. Without seeing more context:
pop = 50;
d = 12;
uye = std::vector<std::vector<float> >(pop, std::vector<float>(d));
The nested for loops that follow work exactly the same, no changes required.
What is wrong?
You're not using std::vector (that's one of the things that's wrong, #FredO covered the other thing).
#include <vector>
int main(){
typedef std::vector<float> inner_vec;
typedef std::vector<inner_vec> outer_vec;
int pop = 50, d = 12;
// first parameter to vector is its size
// second is what every element should be initialized to
outer_vec uye(pop, inner_vec(d));
for(unsigned n = 0; n < uye.size(); ++n){
for(unsigned m = 0; m < uye[n].size(); ++m){
uye[n][m] = (float)n*m;
}
}
}

How do you return a 2d array in C++?

How do I return a 2d array in C++?
For example, I have the following method in java:
public static int[][] getFreeCellList(int[][] grid) {
// Determine the number of free cells
int numberOfFreeCells = 0;
for (int i=0; i<9; i++)
for (int j=0; j<9; j++)
if (grid[i][j] == 0)
numberOfFreeCells++;
// Store free cell positions into freeCellList
int[][] freeCellList = new int[numberOfFreeCells][2];
int count = 0;
for (int i=0; i<9; i++)
for (int j=0; j<9; j++)
if (grid[i][j] == 0) {
freeCellList[count][0] = i;
freeCellList[count++][1] = j;
}
return freeCellList;
}
I'm trying to replicate this in C++. Normally, I would pass in the 2d array i wanted to return as reference parameter of the method in C++.
However, as you see in the method above the size of the array being returned isn't known until run-time.
So, in this case I'm guessing I need to actually return a 2d array, right?
You can use a vector of a vector as well.
typedef vector<vector<int> > array2d_t;
array2d_t etFreeCellList(array2d_t grid) {
// ...
array2d_t freeCellList;
// Determine the number of free cells
int numberOfFreeCells = 0;
for (int i=0; i<9; i++)
for (int j=0; j<9; j++)
if (grid[i][j] == 0) {
freeCellList[count][0] = i;
freeCellList[count++][1] = j;
}
return freeCellList;
}
The inner arrays seem to be fixed to size of 2. You could therefor use a vector of array
static std::vector< array<int, 2> > getFreeCellList(int grid[][9]) {
// Determine the number of free cells
int numberOfFreeCells = 0;
for (int i=0; i<9; i++)
for (int j=0; j<9; j++)
if (grid[i][j] == 0)
numberOfFreeCells++;
// Store free cell positions into freeCellList
std::vector< array<int, 2> > freeCellList(numberOfFreeCells);
int count = 0;
for (int i=0; i<9; i++)
for (int j=0; j<9; j++)
if (grid[i][j] == 0) {
freeCellList[count][0] = i;
freeCellList[count++][1] = j;
}
return freeCellList;
}
Usage is like
int x[9][9] = { ... };
std::vector< array<int, 2> > pa = getFreeCellList(x);
No need for manual memory management since you use std::vector. array is in boost, but you can quickly write a similar class manually
template<typename E, int N>
struct array {
E &operator[](int I) { return data[I]; }
E data[N];
};
The data member is an array of N elements of type E.
Alternatively, you can write this using low-level 2d arrays. Since the inner dimension is fixed in your code, you can actually allocate a real, native 2d array instead of a complicated 1d array of pointers to separate buffers:
static identity<int[2]>::type *getFreeCellList(int grid[][9]) {
// Determine the number of free cells
int numberOfFreeCells = 0;
for (int i=0; i<9; i++)
for (int j=0; j<9; j++)
if (grid[i][j] == 0)
numberOfFreeCells++;
// Store free cell positions into freeCellList
int (*freeCellList)[2] = new int[numberOfFreeCells][2];
int count = 0;
for (int i=0; i<9; i++)
for (int j=0; j<9; j++)
if (grid[i][j] == 0) {
freeCellList[count][0] = i;
freeCellList[count++][1] = j;
}
return freeCellList;
}
Now you can use it like
int x[9][9] = { ... };
// equivalent: identity<int[2]>::type *pa = ...;
int (*pa)[2] = getFreeCellList(x);
// ...
delete[] pa;
Notice the use of identity (from boost or see below) to simplify the syntax. You would need to write the following otherwise
static int (*getFreeCellList(int grid[][9]))[2] {
// ...
}
// identity implementation (for working around the evil C++ syntax)
template<typename T>
struct identity { typedef T type; };
You can put it in a struct and then return the struct. Otherwise C++ doesn't allow returning arrays. You can also return a pointer to the first element (of flat 1D array or fully dynamic 2D array).
You can't return an arbitrary-sized 2d array, just as you can't pass an arbitrary-sized 2d array as a parameter.
C++ arrays are horrible compared to Java arrays. Don't touch them! Use a vector instead.
A construct like
int[][]
in C and C++ only exists for static data, such as
int[][] =
{
{1, 2},
{0, 1}
};
where the compiler can determine the size of the elements at compile time. If you know the size of the inner arrays at compile time - or if you can just can make them fix, then use a typedef such as:
typedef int[16] IntArr16;
Then your function can return a array of this type
IntArr16* getFreeCellList(...).
This all is plain C. Other possibilities are (as explained by dirkgently) to return stl containers.
It's more of a C-style solution than a C++-style solution, but you can always return a structure like
struct {
int dimension_one;
int dimension_two;
void* pArray;
} return_type_t;
Allocate your 2D array dynamically, store the two array dimensions and a pointer to the allocated memory in the structure, and pass that back to the caller.

Using dynamic multi-dimensional arrays in c++

I am making a C++ program that checks if given aray is a latin square. I need to use a dynamic multi-dimensional array that stores given latin square. But I cant pass the array to a function that does the checking...
Currently I have such code for calling the function:
int squaretest(int **p, int n, int sum) {
//some code
};
And this code is for creating the array:
int main() {
//some code. n - length of one row, sum - sum of elements in one row.
int a;
int **lsquare;
lsquare = new int*[n];
for (int i=0;i<=n-1;i++) for (int j=0;j<=n-1;j++) {
cin >>a;
lsquare[i][j] = a;
}
blocktest(lsquare,n,sum);
//some code
};
The code compiles (i am using Geany IDE and G++ compiler) but when I run it in terminal, after the first imput, that has to be stored in block[0][0] I get Segmentation fault error. What's wrong with my code and what is the correct sollution?
To be able to do that.. You actually need to do this:
int **lsquare = new int*[n];
for (int i=0; i<n; ++i)
lquare[i] = new int[n];
for (int i=0; i<n; i++)
for (int j=0; j<n; j++)
cin >> lsquare[i][j];
blocktest(lsquare,n,sum);
The better system would be to do:
int *lsquare = new int[n*n];
for (int i=0; i<n; ++i)
for (int j=0; j<n; ++j)
cin >> lsquare[i + j*n];
blocktest(lsquare, n, sum);
You forgot to allocate memory for second dimension of the matrix.
int **lsquare;
lsquare = new int*[n];
for (int i=0; i<n; ++i){
lsquare[i] = new int[n];
....}
nobody writes
for (int i=0;i<=n-1;i++){...}
Do instead
for (int i=0; i<n; ++i){...}
You have an array of pointers in lsquare.
You might want to just do something like:
lsquare = new int[n * n];
That way you can then fill in this square, but the type is then:
int *lsquare
What you are actually creating an array of arrays. Not only do you need to allocate the array of arrays using new, but also you must allocate all n arrays. You'll want to have the outer loop of your nested for loop allocate each of the n sub-arrays.
lsquare = new int*[n];
for (int i=0;i<=n-1;i++)
{
lsquare[i] = new int[n];
for (int j = 0;j<=n-1;j++)
{
//...
You made yourself a pointer pointer that can be used as a matrix, allocated one row for it, then proceeded to act like you'd allocated an entire n*n matrix. You will indeed get a segfault if you run that.
You need to allocate enough space for n*n elements, not just n of them.
A less error-prone solution might be to use a std::vector of std::vectors.
You have to allocate space for the second dimension too, add this after you allocate lsquare:
for(int i = 0; i < n; ++i)
{
lsquare[i] = new int[n];
}