Allocating a 2d integer array in C - c

I'm trying to dynamically allocate a 2D INT array in C in order to return a transposed matrix, I've done several research on the topic, and it should work this way, however I keep struggling with the program.
I tried it many different ways now (offset, pointer arithmetic), I didn't find a fix for the problem.
I'm either getting trash values or the program crashes (no seg fault, error code crash).
I'm also loooking for a proper version to allocate the memory, I've seen several versions on stackoverflow, the one I would preferrably like to use, is allocating pointer space and the integer space afterwards (the one I'm trying to use in the example below).
// Convert a matrix to it's transposed version. Returns a two dimensional array (pointer)
int **getTransposedMatrix(int *matrix, int dimension_h, int dimension_w){
int **transposedMatrix = (int **) malloc(dimension_w * sizeof(int*));
for(int row=0; row<dimension_w; row++){
transposedMatrix[row] = (int*) malloc(dimension_w * sizeof(int));
}
for(int row=0; row<dimension_h; row++){
for(int column=0; column<dimension_w; column++){
transposedMatrix[column][row] = *(matrix + row * dimension_w + column);
printf("%d ", transposedMatrix + (row * dimension_w + column));
}
printf("\n");
}
return **transposedMatrix;
}
I appreciate any help :)

I would not bother with a "2D array" such as the one you are setting up, where you're allocating the rows separately. Below is my version which uses a single array and calculates offsets into it accordingly.
int *getTransposedMatrix(int *matrix, int dimension_w, int dimension_h)
{
int *transposed = malloc(dimension_w * dimension_h * sizeof(int));
for (int row = 0; row < dimension_h; row++) {
for (int col = 0; col < dimension_w; col++) {
transposed[col * dimension_h + row] = matrix[row * dimension_w + col];
}
}
return transposed;
}
ideone with some test examples

Related

MPI_Gather on 2D matrix only showing data gather from master process [duplicate]

This question already has answers here:
MPI_Bcast a dynamic 2d array
(5 answers)
Closed 2 years ago.
I am trying to use MPI_Gather to gather individual two-dimensional arrays into the master process for it to then print out the contents of the the entire matrix. I split the workload across num_processes processes and have each work on their own private matrix.
I'll give a snippet of my code along with some pseudo-code to demonstrate what I'm doing. Note I created my own MPI_Datatype as I am transferring struct types.
Point **matrix = malloc(sizeof(Point *) * (num_rows/ num_processes));
for (i = 0; i < num_rows/num_processes; i++)
matrix [i] = malloc(sizeof(Point) * num_cols);
for( i = 0; i< num_rows/num_processes; i++)
for (j = 0; j < num_cols; j++)
matrix[i][j] = *Point type*
if (processor == 0) {
full_matrix = malloc(sizeof(Point *) * num_rows);
for (i = 0; i < num_rows/num_processes; i++)
matrix [i] = malloc(sizeof(Point) * num_cols);
MPI_Gather(matrix, num_rows/num_processes*num_cols, MPI_POINT_TYPE, full_matrix, num_rows/num_processes*num_cols, MPI_POINT_TYPE, 0, MPI_COMM_WORLD);
} else {
MPI_Gather(matrix, num_rows/num_processes*num_cols, MPI_POINT_TYPE, NULL, 0, MPI_DATATYPE_NULL, 0, MPI_COMM_WORLD);
}
// ...print full_matrix...
The double for-loop prior to the gather computes the correct values as my own testing showed, but the gather onto full_matrix only contains the data from its own processes, i.e. the master process, as its printing later showed.
I'm having trouble figuring out why this is given the master process transfers the data correctly. Is the problem how I allocate memory for each process?
The problem is that MPI_Gather expects the contents of the buffer to be adjacent in memory, but calling malloc repeatedly doesn't guarantee that, as each invocation can return a pointer to an arbitrary memory position.
The solution is to store the Matrix in a whole chunk of memory, like so:
Point *matrix = malloc(sizeof(Point) * (num_rows / num_processes) * num_cols);
With this method you will have to access the data in the form matrix[i * N + j]. If you want to keep the current code, you can create the adjacent memory as before, and use another vector to store a pointer to each row:
Point *matrixAdj = malloc(sizeof(Point) * (num_rows / num_processes) * num_cols);
Point **matrix = malloc(sizeof(Point *) * num_rows);
for (int i = 0; i < num_rows; ++i) {
matrix[i] = &matrixAdj[i * num_rows];
}

Merging k sorted arrays - problem with memory

The objective is to sort a i x j matrix of words in a 1D matrix of words in alphabetical order(every row in the original matrix is already sorted). The matrix is read from a file and stored in a three star pointer ***index, it is dynamically allocated like this (in a separate function):
char ***index;
index= (char ***) malloc(*row * sizeof(char **));
...
for (int i = 0; i < *row; ++i){
index[i]= (char **) malloc(*col * sizeof(char **));
for (int j=0; j<*col; j++) {
fscanf(fp,"%s",tmp);
index[i][j]=strdup(tmp);
}
}
I then pass the index to my sorting function: char **sort_data(char ***index, int row,int col).
It is nothing special just a merge sort algorithm that:
checks the first elements of each row of ***index
moves the "smallest" word to **sortedIndex
substitutes the sorted word with a new one from the same row.
char **sort_data(char ***index, int row,int col){
int i,posInIndex,smallestCharPos,*tracker;
char **sortedindex,*buffer;
sortedindex=(char **) malloc((row*col)*sizeof(char*));
tracker= (int*) calloc(row, sizeof(int));
posInIndex=0;
while (posInIndex<row*col) {
smallestCharPos=-1;
for (i=0; i<row; i++) {
if ((smallestCharPos==-1)||(strcmp(index[i][tracker[i]], buffer)<0)) {
smallestCharPos=i;
buffer=index[i][tracker[i]];
}
}
sortedindex[posInIndex]=index[smallestCharPos][tracker[smallestCharPos]];
posInIndex++;
tracker[smallestCharPos]++;
}
free(tracker);
return (sortedindex);
}
After some iterations(depends on matrix size) of the for loop, I get a EXC_BAD_ACCESS (code=1, address=0x14000001f5) at the if statement which leads me to believe it's an issue with my memory allocation but i cannot spot the mistake.
An example of a matrix to sort would be (this particular matrix gives me trouble after 10 iterations of the for loop):
milano torino venezia
bari genova taranto
firenze napoli roma
bologna cagliari palermo
The problem is that you don't track when you are done with a row. Even if you have already used all words of a row, you just continue looking at the row as if there are more words to handle.
You need to add some code to skip the rows that are fully handled already.
Try changing this:
if ((smallestCharPos==-1)||(strcmp(index[i][tracker[i]], buffer)<0)) {
...
}
to
if (tracker[i] < col)
{
if ((smallestCharPos==-1)||(strcmp(index[i][tracker[i]], buffer)<0)) {
...
}
}

Getting value from dynamically allocated 2D array

I'm new to C programming so I am probably doing something really stupid here. I am trying to get the value from a 2D array that I read in from a text file ~70m lines.
When running the code, I get a seg fault and I have narrowed it down to line 10: if (i == graph[j][0])
void convertToCSR(int source, int maxNodes, int maxEdges, int* vertices, int* edges, int** graph) {
int i;
int j;
int edge = 0;
for (i = 0; i < maxNodes; i++) {
vertices[i] = edge;
for (j = 0; j < maxEdges; j++) {
if (i == graph[j][0]) {
//Sets edges[0] to the first position
edges[edge] = graph[j][1];
printf("new edge value: %d\n", edge);
edge++;
}
}
}
vertices[maxNodes] = maxEdges;}
I have tried this with smaller datasets e.g 50 bytes and it works fine. With further testing, I print out the value of graph[0][0] and I get a seg fault.
The graph has loaded the data and was allocated like this:
int num_rows = 69000000;
graph = (int**) malloc(sizeof(int*) * num_rows);
for(i=0; i < num_rows; i++){
graph[i] = (int*) malloc(sizeof(int) * 2 );
}
I am also able to get the value of graph[0][0] outside of this method but not inside.What am I doing wrong? I appreciate any help.
EDIT: In my main method, I am doing the following:
readInputFile(file);
int source = graph[0][0];
convertToCSR(source, maxNodes, maxEdges, nodes, edges, graph);
I have the correct value for the variable : source.
It seg faults in the convertToCSR method.
You’re using num_rows to store a number bigger than int capacity.
So the actual value int num_rows is not 69000000, because of the Overflow.
Try to use long unsigned int num_rows instead.

How to populate a bidimensional array in the reverse way - C

I'm trying to populate a bidimensional array in the reverse way but I'm getting always the same error: core dump.
When I say reverse way I mean, usually we do something like
for(int i=0; i<MaxColumns; i++)
for(int b=0; i<MaxRows; b++)
array[i][b] = random value;
What I'm trying to do is for each row, I want to populate that single row on every column and then pass to the next row and do the same. At this time I'm declaring dynamically a new row for each column.
This is what I was trying:
int i = atoi(argv[1]);
int **array = (int**)malloc(i * sizeof(int*));
for (lines =0; lines <MAXLINES; lines ++) {
for (colunms =0; colunms <i; colunms ++) {
array[colunms] = (int*)malloc(1 * sizeof(int));
v=colunms+lines;
array[colunms][lines]=v;
}
}
And the error goes on:
array[colunms][lines]=v;
------ LAST UPDATE TO PROBLEM ----
Already updated and although I tried this code
for (lines =0; lines <MAXLINES; lines ++) {
array[colunms] = (int*)malloc(colunms * sizeof(int));
for (colunms =0; colunms <i; colunms ++) {
v=colunms+lines;
array[colunms][lines]=v;
}
}
I keep getting core dumped on:
array[colunms][lines]=v;
Thats simple enough. Instead of:
for(int i=0; i<MaxColumns; i++)
for(int b=0; i<MaxRows; b++)
array[i][b]=random value;
Use:
for(int b=0; i<MaxRows; b++)
for(int i=0; i<MaxColumns; i++)
array[i][b]=random value;
Your error though is in:
array[colunms] = (int*)malloc(1 * sizeof(int));
You are allocating space for 1 element of int where you should be allocating for colunms * sizeof(int). You should also do that outside the inner loop, like this:
int **array = (int**)malloc(MAXLINES * sizeof(int*));
for (lines =0; lines <MAXLINES; lines ++) {
array[lines] = (int*)malloc(i * sizeof(int));
for (colunms =0; colunms <i; colunms ++) {
v=colunms+lines;
array[lines][colunms] = v;
}
}
Also, even though this code should work, it can be a problem in the future to assume this as array[colunms][lines] where it should be array[lines][colunms].
Why? Because with array[lines][colunms] each array[line] represents a complete row with all its columns, which is a lot more practical for most cases.
In this form you will be able to declare functions to handle single records instead of handing it the entire "table".

returning a multidimensional pointer in c

error lvalue returned as left operand of assignment
What is the error in this program;
int(*matrix)[row][col];
int i = 0;
if(n == 1)
{
for (int i = 0; i < no_matrices; i++)
{
printf("Matrix %d", i + 1);
(matrix + i) = GetMatrixU(row, col); // (error here)
}
}
int* GetMatrixU(int row, int col)
srand(time(NULL));
int(* matrix)[col] = malloc(col*sizeof(int));
for (int i = 0; i < row; i ++)
{
for (int j = 0; j < col; j ++)
{
matrix[i][j] = rand()%100;
}
}
return matrix[];
}
The problem is this line:
(matrix + i) = GetMatrixU(row, col);
This tries to make an assignment. The expression on the right is evaluated; this is the "r-value" ("r" for "right"). Then the result should be assigned to the expression on the left, which is the "l-value" ("l" for "left").
Well, (matrix + i) is not a valid l-value. matrix by itself is a single pointer to a two-dimensional array. In C, you can't just specify a pointer value and assign to it; you must use the * operator to dereference the array, and assign through that.
Here is a short code sample that shows how to dereference a pointer, and then repeats your error.
main()
{
int a[10];
*(a + 1) = 0; // proper use of * to dereference
a + 1 = 0; // will not compile; error is "l-value required"
}
But in C, there is a shortcut way to add to a pointer and then dereference it. It is the use of square brackets and an index value:
a[1] = 0; // index the array
In C, the expressions *(a + i) and a[i] mean exactly the same thing, by definition.
http://en.wikipedia.org/wiki/C_syntax#Accessing_elements
It looks like you are trying to create a random matrix, one row at a time. And you are allocating memory for each row. Your basic matrix declaration should be an array of pointers to rows.
int *matrix[rows];
for (i = 0; i < rows; ++i)
{
// either of these lines will work; pick just one
*(matrix + i) = AllocateRandomRow(cols); // explicit add-and-dereference
matrix[i] = AllocateRandomRow(cols); // simpler: just index array
}
I favor the second, simpler syntax for solving this problem. You are indexing an array; just use the square brackets.
Here is a free online text that describes how to dynamically allocate a matrix.
http://www.eskimo.com/~scs/cclass/int/sx9b.html
Here's an example of simpler case to understand this more complex case:
int b = 4;
int *a = &b; // Allowed and works because a is a pointer to an integer
a+1 = 5; // Not allowed no idea about the type of a+1 and it could be used!!
Why this relates to your problem ?
int(*matrix)[5][5];
printf("%p\n",matrix);
printf("%p\n",matrix+1);
Output
0xb7753000
0xb7753064
Difference between the above pointers is of 6*16 + 4 = 100. This number is nothing but row*col*sizeOf(int) = 5*5*4 = 100
Therefore, what you want to do was accessing the cells in matrix, however what you are actually doing is trying to access a memory that your not allowed to use as in the first simple example.
Example of what you are actually doing vs what you wanted the program to do:
int(*matrix)[5][5];
matrix + 0 => address of matrix
matrix + 1 => address of matrix + 100 bytes (you expected + 4 bytes instead)
matrix + 2 => address of matrix + 200 bytes (you expected + 8 bytes instead)
etc...

Resources