Binary I/O to file with 2 dimensional dynamic array - c++

I am having troubles with I/O to file with 2 dimensional dynamic array. It compiles good but it does not work as I want. Example, I save "map" of numbers 1 and after this I change number in source code to example 5 and compile it, now I load my "map" of numbers 1 but when it writes in cycle for at the end it, the output is 5 not 1. Please can somebody help to fix the code?
#include <iostream>
#include <fstream>
int main()
{
int ** array;
array = new int*[20];
for(int y=0;y<20;y++)
array[y] = new int[30];
for(int y=0;y < 20;y++)
for(int x=0;x < 30;x++)
array[y][x] = 1;
int volba = 1;
std::cin >> volba;
if(volba)
{
std::ifstream in("map",std::ios::in | std::ios::binary);
if(!in.is_open())
std::cout << "in map open error\n";
in.read((char*)&array, sizeof(array));
in.close();
std::cout << "loaded\n";
}
else
{
std::ofstream out("map",std::ios::out | std::ios::binary);
if(!out.is_open())
std::cout << "out map open error\n";
out.write((char*)&array, sizeof(array));
out.close();
std::cout << "saved\n";
}
std::cout << "array\n";
for(int y=0;y < 20;y++)
{
for(int x=0;x < 30;x++)
std::cout << array[y][x] << " ";
std::cout << std::endl;
}
for(int y=0;y<20;y++)
delete [] array[y];
delete [] array;
return 0;
}

The main problem is this: Hereby
array = new int*[20];
you allocate an array of pointers, and this will not become a two dimensional array as you later do:
array[y] = new int[30];
Note that there is a difference between this
// array of pointers to integer arrays
int ** array = new int*[20];
for(int y=0;y<20;y++)
array[y] = new int[30];
and this
// two dimensional integer array
int array[20][30];
You cannot assume that your array of arrays will lie in contiguous memory.
Besides:
Hereby
out.write((char*)&array, sizeof(array));
you just write out the pointer, not the actual data. Try to print the sizeof(array):
#include <iostream>
int main() {
int * array = new int[10];
std::cout << sizeof(array) << std::endl; // probably prints 4 or 8
return 0;
}
Conclusion: Unless you need to implement this for educational purposes, std::vector will far more conveniently serve you memory management for free. Also have a look on Boost Serialization. It provides functionality for serialization of STL collections.

The error is in the fact that sizeof(array) equals to the size of a pointer, not the size of dynamically allocated memory. As an effect, you read/write only 4 (or 8) bytes. Use actual array size (in this case 20*30) instead of sizeof(array).

Related

c++ array of pointers and memory address allocation

Can someone explain how an array of pointers implementation of c++ dynamically?
Is the below code correct?
If so,
int *ptr[5];
for (int i = 0; i < 5; i++)
{
int size = 2;
ptr[i] = new int [size] ;
//*(ptr + i) = new int[size]; this is the same as above line
cout << &ptr[i] << endl; ----------> line 1
cout << ptr[i] << endl; -----------> line 2
}
What is actually printing in line 1 and 2 ?
this is the addresses i get for line 1
0x7fff88f805d0
0x7fff88f805d8
0x7fff88f805e0
0x7fff88f805e8
0x7fff88f805f0
this is the addresses I get for line 2
0x55f946348ef0
0x55f946349330
0x55f946349360
0x55f946349390
0x55f9463493c0
Can somebody explain this whole mess of pointer arrays.
The picture provides a graphical explanation to the problem if anyone gets
confused with the array of pointers concept with dynamically allocating the array of pointers to new int or any other type array
int *ptr[2]; // statically declared pointer array stack
int p [2];
for (int i = 0; i < 2; i++)
{
int size = 2;
ptr[i] = new int[size];
cout << i << " array of int " << endl;
//*(ptr + i) = new int[size];
for (int j = 0; j < size; j++)
{
cout << "value : " ;
cout << *(ptr[i] + j) ; // <------- this should give 0's as value
//cout << (ptr[i])[j] ; <------ same thing
cout << " address :";
cout << ptr[i] + j << endl; //<----- these are in order as well since it's an array of type int
}
}
0 array of int
value : 0 address :0x564c9ede32c0
value : 0 address :0x564c9ede32c4
value : 0 address :0x564c9ede32c8
1 array of int
value : 0 address :0x564c9ede32e0
value : 0 address :0x564c9ede32e4
value : 0 address :0x564c9ede32e8
I am assuming you want to perform operation on dynamic array like adding element and printing;
Remember:In int *ptr=new int[5]; sizeof(ptr) is 8 bytes on stack memory and array will be stored in heap memory.
We will fetch the element via pointer ptr and every element will be fetched as per type of array (say int ) then ptr will go to 0th index element and read the data of it as int type (only 4 bytes as int is of 4 byte generally) and move to next index till end.
Look into code below:
#include <iostream>
using namespace std;
int main() {
int *ptr=new int[5]; //let size = 5
for(int i=0; i<5;i++){
cin>>ptr[i];
}
for(int i=0; i<5;i++){
cout<<&ptr[i]<<":"; //this will print every element's address per iteration
cout<<ptr[i]<<endl; //this will print every element as per input you gave
}
delete []ptr; //remember it's not delete ptr ask if required
return 0;
}
Now See the the output and dry run yourself you can understand
Output
0x556999c63e70:1
0x556999c63e74:2
0x556999c63e78:3
0x556999c63e7c:4
0x556999c63e80:5
Benefit of dynamic array is you can create dynamic sized array by taking size input as per user choice pass that variable is size of dynamic array
i.e you can change above size=5 to 'N' a variable one .
I think this might help you else you can ask for any further clarification.

dynamically allocate an Array

I want to declare a 2D Array without an initial size. It keeps on giving me an error:
Error C2078: too many initializes.
I have tried to dynamically allocate my array but nothing worked out so far as I am not too familiar with dynamic allocation. My question is If there is a possible way to declare an Array without an initial size and if so what is the most efficient way to do it ?
I wrote a simple program using pointers, new and delete functions. You can add more functionality to it.
#include <iostream>
using namespace std;
int main()
{
int size;
cout << "Input size of 2D array : ";
cin >> size;
int *ptr; // Declare Pointer
ptr = new int[size*size]; // Allocate memory of all elements in 2D array
for (int i = 0; i < size*size; i++) {
*(ptr + i) = 0; // Initialize every element to 0
}
cout << "Printing the 2D Array" << endl << endl;
int iterSize = 0;
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
cout << *(ptr + iterSize) << " ";
}
cout << endl;
}
delete [] ptr; // ptr memory is released
return 0;
}
Here is the output initializing all elements to 0:
my question is If there is a possible way to declare an Array without an initial size and if so what is the most efficient way to do it ?
Sure, you could provide a vector of vectors to represent a 2D array (let's say of integer values):
std::vector<std::vector<int>> my2DArray;
Well, regarding efficiency maybe performance and memory fragmentation wise it's better to wrap a 1D vector kept internally with an interface that allows 2D coordinate access.
That would require you to know and specify the dimension limits though.
So if you really want to keep a 2D structure without initial size the above mentioned vector of vectors is the way to go.

Storing array's of integers on the heap and accessing them via pointers

I'm hoping someone can shed some light on where I am going wrong with pointers.. I've read countless web pages and tried various things but for some reason my code is returning jibberish (which I'm guessing may be the memory addresses instead of the data within my array). The purpose of the program is to create an array of 100 elements on the heap, pass this array by a pointer to a function (along with two integer variables start and end); a new array will be created on the heap (this comprises of a chunk of the original array using the start and end variables) and the pointer to this array is passed back to the main method so that the new array can be outputted. My problem is not only is the output seeming to be the location not the value, but also it seems 100 values are outputted not 20 as should be expected. I've spent hours trying to figure out where I have gone wrong and just when I think I understand the concept of pointers my faith is destroyed by red squigglies and incorrect outputs. Please HELP! My code is as follows:
#include "stdafx.h"
#include <iostream>
#include <time.h>
using namespace std;
double* getSubArray(double*, int, int);// Declare a function that will get the sub array
int _tmain(int argc, _TCHAR* argv[])
{
const int size = 100;// Declare the size of the array
double* pA;// Declare the variable to hold the pointers to the data in array
double* pB;
int start = 15;
int end = 35;
pA = new double[size];// Create space for the array
srand(clock());// Seed the program to the computers current time so that random gets a different set of random numbers everytime it is run
// Use a for loop to traverse through each element of the array (starting at index 0) placing a number defined by the random function that is no higher than 250
for (int i = 0; i < size; i++)
{
pA[i] = rand()%250;
}
cout << "An Array of 100 numbers is created and stored in the heap, these values are:" << endl;
// Output the Array for the user to see
for (int j = 0; j < size; j++)
{
// Place 10 numbers on each line
if (j % 10 == 0)
{
cout << endl;
}
cout << *(pA + j) << " ";
}
cout << endl << "The program will build a second array using the data between the indexes " << start << " & " << end << endl;
pB = getSubArray(pA, start, end);// Pass the data to the method
// Output second array for user to compare
for (int k = 0; k < size; k++)
{
// Place 10 numbers on each line
if (k % 10 == 0)
{
cout << endl;
}
cout << *(pB + k) << " ";
}
system("pause");
return 0;
}
double* getSubArray(double* pA, int start, int end)
{
double* pB = new double[end-start];// Declare space in the heap for the new array whoes size is the size of the criteria given
for (int i = 0; i < (end - start); i++)
{
for (int j = start; j < end; j++)
{
*(pB + 0) = pA[j];
}
}
return pB;
}
*(pB + 0) = pA[j];
That keeps writing to the first element of the array. Surely you want to write to each element in turn:
for (int i = start; i < end; ++i) {
pB[i-start] = pA[i];
}
or if you don't want to write your own loop
std::copy(pA+start, pA+end, pB);
Don't forget to delete[] everything you new[] or, to save mucking around with low-level memory management, use std::vector to manage the dynamic arrays for you.

How to a resize a dynamic array?

Let's say I have a dynamic array:
int* p;
ifstream inFile("pop.txt");
int x;
while (inFile >> x)
{
// ????
}
How do I resize p so I am able to to fit x in as like an array. I don't want to use a vector or static array as I am trying to learn the language. I need to use pointers because I don't know the initial size. Any attempt is appreciated.
The simplest answer is that you should use higher level components than raw arrays and raw memory for the reading. That way the library will handle this for you. A simple way of reading a set of numbers into an application (without error handling) could be done with this simple code:
std::vector<int> data;
std::copy(std::istream_iterator<int>(inFile), std::istream_iterator<int>(),
std::back_inserter(data));
The code creates a couple of input iterators out of the stream to read int values, and uses a back_inserter iterator that will push_back onto the vector. The vector itself will manage growing the memory buffer as needed.
If you want to do this manually you can, you just need to allocate a larger chunk of memory, copy the first N elements from the old buffer, release the old buffer and continue reading until the larger buffer gets filled, at which point you follow the same procedure: allocate, copy, deallocate old, continue inserting.
You can't resize it. All you can do is allocate a new bigger array, copy everything over from the old array to the new array, then free the old array.
For instance (untested code)
int array_size = 10;
int* array = new int[array_size];
int array_in_use = 0;
int x;
while (in >> x)
{
if (array_in_use == array_size)
{
int* new_array = new int[2*array_size];
for (int i = 0; i < array_size; ++i)
new_array[i] = array[i];
delete[] array;
array = new_array;
array_size *= 2;
}
array[array_in_use++] = x;
}
It's tedious, and I'm not convinced it's a good thing for a beginner to be doing. You'd learn more useful stuff if you learned how to use vectors properly.
You could always use realloc(). It's a part of the C Standard Library, and the C Standard Library is a part of the C++ Standard Library. No need for tedious news and deletes.
#include <cstdlib>
#include <iostream>
#include <fstream>
int main(void)
{
int* array = nullptr;
unsigned int array_size = 0;
std::ifstream input("pop.txt");
for(int x; input >> x;)
{
++array_size;
int* array_failsafe = array;
array = static_cast<int*>(realloc(array, sizeof(x) * array_size));
if(array == nullptr)
{
std::cerr << "realloc() failed!" << std::endl;
free(array_failsafe);
return EXIT_FAILURE;
}
array[array_size-1] = x;
}
for(unsigned int i = 0; i < array_size; ++i)
{
std::cout << "array[" << i << "] = " << array[i] << std::endl;
}
free(array); // Don't forget!
return EXIT_SUCCESS;
}

Using MPI_Gatherv() and MPI_Datatype to 'gather' dynamically allocated 2D arrays in C++

I think the easiest way to describe the problem is with a simple code. On each processor I have dynamically allocated '2D arrays' (achieved via the new*[rows],new[cols] formalism, see code below for clarification). Rightly or wrongly, I'm trying to use a committed MPI_Datatype to help me do MPI_Gatherv() to gather all the arrays into a single 2D array on the root processor.
Here's the code, and below it I highlight to salient points of it (it should be very easy to understand if compiled and ran - it asks for the dimensions of the array you desire):
#include <iostream>
#include <string>
#include <cmath>
#include <cstdlib>
#include <time.h>
#include "mpi.h"
using namespace std;
// A function that prints out the 2D arrays to the terminal.
void print_2Darray(int **array_in,int dim_rows, int dim_cols) {
cout << endl;
for (int i=0;i<dim_rows;i++) {
for (int j=0;j<dim_cols;j++) {
cout << array_in[i][j] << " ";
if (j==(dim_cols-1)) {
cout << endl;
}
}
}
cout << endl;
}
int main(int argc, char *argv[]) {
MPI::Init(argc, argv);
// Typical MPI incantations...
int size, rank;
size = MPI::COMM_WORLD.Get_size();
rank = MPI::COMM_WORLD.Get_rank();
cout << "size = " << size << endl;
cout << "rank = " << rank << endl;
sleep(1);
// Dynamically allocate a 2D square array of user-defined size 'dim'.
int dim;
if (rank == 0) {
cout << "Please enter dimensions of 2D array ( dim x dim array ): ";
cin >> dim;
cout << "dim = " << dim << endl;
}
MPI_Bcast(&dim,1,MPI_INT,0,MPI_COMM_WORLD);
int **array2D;
array2D = new int*[dim];
for (int i=0; i<dim; i++) {
array2D[i] = new int[dim](); // the extra '()' initializes to zero.
}
// Fill the arrays with i*j+rank where i and j are the indices.
for (int i=0;i<dim;i++) {
for (int j=0;j<dim;j++) {
array2D[i][j] = i*j + rank;
}
}
// Print out the arrays.
print_2Darray(array2D,dim,dim);
// Commit a MPI_Datatype for these arrays.
MPI_Datatype MPI_ARRAYROW;
MPI_Type_contiguous(dim, MPI_INT, &MPI_ARRAYROW);
MPI_Type_commit(&MPI_ARRAYROW);
// Declare 'all_array2D[][]' which will contain array2D[][] from all procs.
int **all_array2D;
all_array2D = new int*[size*dim];
for (int i=0; i<size*dim; i++) {
all_array2D[i] = new int[dim](); // the extra '()' initializes to zero.
}
// Print out the arrays.
print_2Darray(all_array2D,size*dim,dim);
// Displacement vector for MPI_Gatherv() call.
int *displace;
displace = (int *)calloc(size,sizeof(int));
int *dim_list;
dim_list = (int *)calloc(size,sizeof(int));
int j = 0;
for (int i=0; i<size; i++) {
displace[i] = j;
cout << "displace[" << i << "] = " << displace[i] << endl;
j += dim;
dim_list[i] = dim;
}
// MPI_Gatherv call.
MPI_Barrier(MPI_COMM_WORLD);
MPI_Gatherv(array2D,dim,MPI_ARRAYROW,all_array2D,&dim_list[rank],&displace[rank],MPI_ARRAYROW,0,MPI_COMM_WORLD);
// Print out the arrays.
print_2Darray(all_array2D,size*dim,dim);
MPI::Finalize();
return 0;
}
The code compiles, but runs into segmentation faults (I compile with 'mpic++' and used 'mpirun -np 2' to use 2 processors):
[unknown-78-ca-39-b4-09-4f:02306] *** Process received signal ***
[unknown-78-ca-39-b4-09-4f:02306] Signal: Segmentation fault (11)
[unknown-78-ca-39-b4-09-4f:02306] Signal code: Address not mapped (1)
[unknown-78-ca-39-b4-09-4f:02306] Failing at address: 0x0
[unknown-78-ca-39-b4-09-4f:02306] [ 0] 2 libSystem.B.dylib 0x00007fff844021ba _sigtramp + 26
[unknown-78-ca-39-b4-09-4f:02306] [ 1] 3 ??? 0x0000000000000001 0x0 + 1
[unknown-78-ca-39-b4-09-4f:02306] [ 2] 4 gatherv2Darrays.x 0x00000001000010c2 main + 1106
[unknown-78-ca-39-b4-09-4f:02306] [ 3] 5 gatherv2Darrays.x 0x0000000100000a98 start + 52
[unknown-78-ca-39-b4-09-4f:02306] *** End of error message ***
mpirun noticed that job rank 0 with PID 2306 on node unknown-78-ca-39-b4-09-4f.home exited on signal 11 (Segmentation fault).
1 additional process aborted (not shown)
The segmentation fault occurs upon execution of the 'print_2Darray(all_array2D,size*dim,dim)' function near the end of the code, where 'all_array2D' is 'supposed to' contain the gathered arrays. More specifically, the code seems to print the 'all_array2D' OK for the bit gathered from the master processor, but then gives the seg fault when the print_2Darray() function starts working on the bits from other processors.
Salient points of code:
I declare an MPI_Datatype that is a contiguous block of memory of sufficient size to store a single row of the 2D arrays. I then use MPI_Gatherv() to try and gathers these rows.
The code's sleep(1) call is just to help the user see the prompt for 'dims' more clearly, otherwise it get's buried between the 'size' and 'rank' couts.
The elements of the 2D array are initialized to values "i*j + rank" where i and j are the row and column indices respectively. My rationale is that the resulting numbers easily give away the rank of the processor that generated that array.
I guess it boils down to me not knowing how properly to MPI_Gatherv() dynamically allocated arrays... Should I be using MPI_Datatypes at all? It's quite important to me that the arrays are dynamically allocated.
I will be very grateful for any help/suggestions! I'm pretty much depleted of ideas!
MPI_Gatherv, MPI_Scatterv, and in fact all other MPI communication calls that take array arguments, expect that array elements are laid out consecutively in memory. This means that in the call MPI_Gatherv(array2D, dim, MPI_ARRAYROW, ...), MPI expects that the first element of type MPI_ARRAYROW starts at the memory location that array2D points to, the second element starts at (BYTE*)array2D + extent_of(MPI_ARRAYROW), the third element starts at (BYTE*)array2D + 2*extent_of(MPI_ARRAYROW), and so on. Here extent_of() is the extent of the MPI_ARRAYROW type, which can be obtained by calling MPI_Type_get_extent.
Clearly the rows of your 2D array are not consecutive in memory since each of them is allocated by a separate invocation of the new operator. Also array2D is not a pointer to the data, but rather a pointer to the vector of pointers to each row. This doesn't work in MPI and there are countless of other questions here on StackOverflow, where this fact is discussed - just search for MPI 2D and see for yourself.
The solution is to use a big chunk of singly allocated memory block with an accompanying dope vector - see this question and the arralloc() function mentioned in the answer.
This problem, involving array allocations, comes up all the time in dealing with C/C++ and MPI. This:
int **array2D;
array2D = new int*[dim];
for (int i=0; i<dim; i++) {
array2D[i] = new int[dim](); // the extra '()' initializes to zero.
}
allocates dim 1d arrays, each dim ints in length. However, there's no reason at all why these should be laid out next to each other - the dim arrays are likely scattered across memory. So even sending dim*dim ints from array2D[0] won't work. The all_array2D is the same; you are creating size*dim arrays, each of size dim, but where they are in relation to each other who knows, making your displacements likely wrong.
To make the arrays contiguous in memory, you need to do something like
int **array2D;
array2D = new int*[dim];
array2D[0] = new int[dim*dim];
for (int i=1; i<dim; i++) {
array2D[i] = &(array2D[dim*i]);
}
and similarly for all_array2D. Only then can you start reasoning about memory layouts.
I just wanted to summarise the solution which #Hristolliev and #JonathanDursi helped me get to.
MPI commands like MPI_Gatherv() work with contiguously allocated blocks of memory, hence use of 'new' to construct 2D arrays which then feed into MPI commands won't work since 'new' doesn't guarantee contiguous blocks. Use instead 'calloc' to make these arrays (see code below as an example).
An important point by #Hristolliev: The 1st and 4th arguments of MPI_Gatherv() must be pointers to the first elements of type MPI_ARRAYROW. Dereferencing the 2D arrays by one level e.g. array2D[0] will achieve this (again, see modified working code below).
The final, working code is given below:
#include <iostream>
#include <string>
#include <cmath>
#include <cstdlib>
#include <time.h>
#include "mpi.h"
using namespace std;
void print_2Darray(int **array_in,int dim_rows, int dim_cols) {
cout << endl;
for (int i=0;i<dim_rows;i++) {
for (int j=0;j<dim_cols;j++) {
cout << array_in[i][j] << " ";
if (j==(dim_cols-1)) {
cout << endl;
}
}
}
cout << endl;
}
int main(int argc, char *argv[]) {
MPI::Init(argc, argv);
// Typical MPI incantations...
int size, rank;
size = MPI::COMM_WORLD.Get_size();
rank = MPI::COMM_WORLD.Get_rank();
cout << "size = " << size << endl;
cout << "rank = " << rank << endl;
sleep(1);
// Dynamically allocate a 2D square array of user-defined size 'dim'.
int dim;
if (rank == 0) {
cout << "Please enter dimensions of 2D array ( dim x dim array ): ";
cin >> dim;
cout << "dim = " << dim << endl;
}
MPI_Bcast(&dim,1,MPI_INT,0,MPI_COMM_WORLD);
// Use another way of declaring the 2D array which ensures it is contiguous in memory.
int **array2D;
array2D = (int **) calloc(dim,sizeof(int *));
array2D[0] = (int *) calloc(dim*dim,sizeof(int));
for (int i=1;i<dim;i++) {
array2D[i] = array2D[0] + i*dim;
}
// Fill the arrays with i*j+rank where i and j are the indices.
for (int i=0;i<dim;i++) {
for (int j=0;j<dim;j++) {
array2D[i][j] = i*j + rank;
}
}
// Print out the arrays.
print_2Darray(array2D,dim,dim);
// Commit a MPI_Datatype for these arrays.
MPI_Datatype MPI_ARRAYROW;
MPI_Type_contiguous(dim, MPI_INT, &MPI_ARRAYROW);
MPI_Type_commit(&MPI_ARRAYROW);
// Use another way of declaring the 2D array which ensures it is contiguous in memory.
int **all_array2D;
all_array2D = (int **) calloc(size*dim,sizeof(int *));
all_array2D[0] = (int *) calloc(dim*dim,sizeof(int));
for (int i=1;i<size*dim;i++) {
all_array2D[i] = all_array2D[0] + i*dim;
}
// Print out the arrays.
print_2Darray(all_array2D,size*dim,dim);
// Displacement vector for MPI_Gatherv() call.
int *displace;
displace = (int *)calloc(size,sizeof(int));
int *dim_list;
dim_list = (int *)calloc(size,sizeof(int));
int j = 0;
for (int i=0; i<size; i++) {
displace[i] = j;
cout << "displace[" << i << "] = " << displace[i] << endl;
j += dim;
dim_list[i] = dim;
cout << "dim_list[" << i << "] = " << dim_list[i] << endl;
}
// MPI_Gatherv call.
MPI_Barrier(MPI_COMM_WORLD);
cout << "array2D[0] = " << array2D[0] << endl;
MPI_Gatherv(array2D[0],dim,MPI_ARRAYROW,all_array2D[0],&dim_list[rank],&displace[rank],MPI_ARRAYROW,0,MPI_COMM_WORLD);
// Print out the arrays.
print_2Darray(all_array2D,size*dim,dim);
MPI::Finalize();
return 0;
}
Compile with mpic++.