As far as i know this two ways to create a matrix should be identical:
First way:
int i;
int **matrix = (int**)malloc(R*sizeof(int*));
for (i=0; i<R; i++)
matrix[i] = (int*)malloc(C*sizeof(int));
Second way:
int matrix[R][C];
with R and C declared as:
#define R 3
#define C 5
My question is, when i pass the second way declared matrix to a function like this:
void myfunction(int **m, int rows, int columns);
with the code:
myfunction(matrix,R,C);
why does it give me a Segmentation fault as soon as i try to touch the values inside the matrix?
The same happens when i pass the first way declared matrix to a function like this:
void myfunction(int m[][C], int rows, int columns);
What am i missing?
The first way allocates an array of pointers to allocated arrays of int.
The 2nd way allocates a single array and uses the C parameter to calculate the correct offset.
They are not interchangeable.
See the bottom part of this page for the differences.
You are accessing the array out of bounds. Then the result is undefined. This line should be corrected as follows
for (i=0; i<R; i++)
matrix[i] = (int*)malloc(C*sizeof(int));
You are accessing memory out of bounds here:
for (i=0; i<C; i++)
matrix[i] = (int*)malloc(C*sizeof(int));
Your R = 3 and C = 5
You allocated memory for R int pointers then, for C pointers you are allocating space for C integer variables.
(Replacing variables with values):
You allocated memory for 3 int pointers then, for 5 pointers you are allocating space for 5 integer variables.
In your FIRST case:
It should give Seg. Fault as soon as you access matrix[3], but anyways it is an Undefined Behaviour, you can't say anything.
In your SECOND case:
The code should work fine, unless you do a same kind of mistake (Mem Access Out-of-bounds) inside myfunction().
Related
To return a two dimensional array with variable dimension lengths allocated dynamically inside a function I've been returning a pointer to an one dimensional array like this:
#include <stdio.h>
#include <stdlib.h>
int (*create_2D_matrix(size_t lin, size_t col))[];
int main() {
size_t lin = 4, col = 5;
int (*m)[col] = create_2D_matrix(lin, col);
for (size_t i=0; i<lin*col; i++){
m[i/col][i%col] = (int) i+1;
}
for (size_t i=0; i<lin; i++){
for (size_t j=0; j<col; j++){
printf("%2d ", m[i][j]);
}
printf("\n");
}
free(m);
return 0;
}
int (*create_2D_matrix(size_t lin, size_t col))[] {
int (*matrix)[col] = malloc(lin * sizeof *matrix);
if (matrix == NULL){
fprintf(stderr, "Memory allocation of 2D matrix has failed.\n");
exit(EXIT_FAILURE);
}
return matrix;
}
GCC compiles this with no warnings (I've tried to activate several warning options that might be related, but nothing I tried complained about it), online Clang also doesn't seem to have a problem with it, and it works as intended.
But when looking what are the recommended ways to return multi dimensional arrays the answers I've found recommend something like passing it as a pointer to a parameter of the function, so that the address to the allocated memory can be set to the pointer inside the function and returned through that, or even to use a normal one dimensional array and do some index math to simulate a multi dimensional array.
I haven't found anything suggesting returning a pointer to a one dimensional array like the code above being mentioned as an alternative method for two dimensional arrays.
So my question is: Is what I've been doing valid C code? Can I return a pointer to an array of variable length like this?
Yes this code is correct. Personally I would use a typedef as I find the syntax for returning pointer-to-array a bit ugly, e.g.:
typedef int intarray[];
intarray *create_2D_matrix(size_t lin, size_t col);
You may find this technique is not mentioned a lot because many C programmers seem to be stuck in the 1980s .
It would also be possible to return void *, which allows your same allocation function to allocate space for an array of any number of dimensions, whether this is a benefit or a drawback is up to you I guess :)
And in both cases the malloc line could also be written as void *matrix = malloc(sizeof(int[lin][col]));
This question already has answers here:
Crash or "segmentation fault" when data is copied/scanned/read to an uninitialized pointer
(5 answers)
Closed 5 years ago.
I have written the following code:
#include <stdio.h>
#include <stdlib.h>
typedef struct _NeuralNetwork{
int input_rows;
int input_columns;
double **inputs;
}NeuralNetwork;
void main(){
// structure variable
NeuralNetwork *nn;
int count;
int i,j;
nn->input_rows = 2;
nn->input_columns = 3;
// create the array of double pointers using # of rows
nn->inputs = (double **)malloc(nn->input_rows * sizeof(double *));
// each pointer gets an array of double values
for (i=0; i<nn->input_rows; i++){
nn->inputs[i] = (double *)malloc(nn->input_columns * sizeof(double));
}
// assign values
count = 0;
for (i = 0; i < nn->input_rows ; i++)
for (j = 0; j < nn->input_columns; j++)
nn->inputs[i][j] = ++count;
// print those values
for (i = 0; i<nn->input_rows; i++)
for (j = 0; j < nn->input_columns; j++)
printf("%f ", nn->inputs[i][j]);
/* Code for further processing and free the
dynamically allocated memory*/
return;
}
When I compile this everything is okay. But after running it, I get a segmentation fault error:
Segmentation fault (core dumped)
I am not sure, where the mistake is. Can somebody help?
Note: When I use nn as structure variable instead of a structure, then everything is fine. But I want to use it as structure pointer and access the structure members via "->" and not via "." since I plan to pass nn as pointer to another function later.
Thank you in advance :)
The variable nn is a pointer, but that pointer is never initialized. You subsequently read and dereference that pointer using an operation such as nn->input_rows = 2;. This invokes undefined behavior.
In this particular case, nn likely contains some garbage value. By dereferencing that pointer value, you are attempting to read from memory you probably aren't allowed to. This is what causes the crash.
By defining nn as an instance of a struct instead of a pointer, as you said you tried, you avoid this issue. You can still however pass a pointer to other functions by taking the address of this variable and passing that to the function, i.e.:
NeuralNetwork nn;
...
myfunction(&nn)
First, do not use void main(), it's non-standard and would eventually cause problems. The right way is int main() or int main(int argc, char** argv). Remember to return a proper value at the end of the main function, possibly 0. Consult the reference here: main function
Second, if you use NeuralNetwork *nn; you must allocate some space for it in memory. It's a pointer to some memory address, if you don't allocate it who knows where it points. That's why you're getting the segfault. You must allocate memory for it in the following way:
NeuralNetwork *nn = malloc(sizeof(NeuralNetwork));
Then it should work properly.
I wrote a program for reading and printing the matrix without making use of array of pointers. The program is reading and printing matrix correctly, but it crashes after the execution. There are no warnings in the program. Unable to find what is wrong with the program. I am using Codeblock+mingw
Also is this method of using pointer to pointer for two dimensional matrix is OK or any better method?
#include <stdio.h>
#include <malloc.h>
int main()
{
int numCols=2;
int numRows=2;
int *cols;
int rowCount;
int colCount;
cols=(int*) malloc(numCols*sizeof(int));
int **rows;
rows= (int**) malloc(numRows*sizeof(cols));
printf("Filling the rows and Columns\n");
for(rowCount=0;rowCount<numRows;rowCount++)
{
printf("Fill Row Number %d\n",rowCount);
for(colCount=0;colCount<numCols;colCount++)
{
printf("Enter the value to be read\n");
scanf("%d",(*(rows+rowCount)+colCount));
}
}
// Printing the values
for(rowCount=0;rowCount<numRows;rowCount++)
{
printf("Print Row Number %d\n",rowCount);
for(colCount=0;colCount<numCols;colCount++)
{
printf("%d\t",*(*(rows+rowCount)+colCount));
}
printf("\n");
}
free(rows);
free(cols);
return 0;
}
You're not allocating memory in the right manner. Your program crashes because of illegal memory access it makes.
What's Cols array for; as you're never storing any integer in it and its extra. Second rows is a an array int* not int. One of the ways to allocate a 2D array will be
int** matrix;
matrix = (int **)malloc(sizeof(int *));
matrix[0] = (int *)malloc(sizeof(int) * c * r);
//To access elements
for(rowCount=0;rowCount<numRows;rowCount++)
{
printf("Fill Row Number %d\n",rowCount);
for(colCount=0;colCount<numCols;colCount++)
{
printf("Enter the value to be read %d %d \n", rowCount, colCount);
scanf("%d",(*matrix+rowCount*numCols)+colCount);
}
}
//free it as
free(matrix);
Its always a good practice to allocate and access row-wise in C to so that memory fetches are not bottle-neck.
Update
Yes you can allocate memory like this.
rows= (int**) malloc(numRows * numCols * sizeof(int)); //Yes sizeof(int).
Its perfectly legal statement in C. It will allocate numRows * numCols sized array of integer pointers with each element of size equal to sizeof(int).
It may cause trouble on 64bit platform where pointers are 8 byte long.
Even assuming it to be 32bit platform there is another problem. How will you dereference rows for your intended purpose? rows[i] will be a pointer to integer i.e. int* type; but doing scanf on that will give you a segmentation fault as row[i] will contain some garbage value and might lead you to some unwanted area in memory.
I have a 1d buffer which i have to re-organize to be accessed as a 2d array. I have pasted my code below:
#include <stdlib.h>
#include <stdio.h>
void alloc(int ** buf, int r, int c)
{
int **temp=buf;
for(int i=0; i<r; i++)
buf[i]=(int *)temp+i*c;
}
void main()
{
int *buffer=(int *)malloc(sizeof(int)*100);
int **p = (int**) buffer;
alloc(p, 4, 4);
//for(int i=0;i<r;i++)
//for(int j=0;j<c;j++)
// printf("\n %p",&p[i][j]);
p[0][3]=10;
p[2][3]=10;
p[3][2]=10; //fails here
printf("\n %d", p[2][3]);
}
The code is crashing when i make the assignment.
I have ran the code for different test cases. I have observed that the code crashes when there is an assignment to p[0][x] followed by assignment to p[x][anything] with the code crashing at the second assignment. This crash is seen only when the first index of the first assignment is 0 and for no other indices with the crash happening at the second assignment having the first index equal to the second index of the first assignment.
For example, in the above code crash happens at p[3][2] after p[0][3] has been executed. If i change the first assignment to p[0][2] then crash would happen at p[2][3]( or p[2][anything] for that matter).
I have checked the memory pointed to by p, by uncommenting the double for loop, and it seems to be fine. I was suspecting writing at illegal memory locations but that has been ruled out by the above observation.
The problem is that your 2D array is actually an array of pointers to arrays. That means you need to have space for the pointers. At the moment you have your pointers in positions 0-3 in the array, but p[0] is also pointing to position 0. When you write to 'p[0,3]' you are overwriting p[3].
One (tempting) way to fix it is to allow the pointers room at the start of the array. So you could change your alloc method to allow for some space at the front. Something like:
buf[i] = (int *)(temp+r) + i*c;
Note the +r adding to the temp. It needs to be added to temp before it is cast as you can't assume int and int * are the same type.
I would not recommend this method as you still have to remember to allocate extra space in your original malloc to account for the array of pointers. It also means you aren't just converting a 1D array to a 2D array.
Another option would be to allocate your array as an array of pointers to individually allocated arrays. This is the normal way to allocate 2D arrays. However this will not result in a contiguous array of data as you have in your 1D array.
Half way between these two options, you could allocate an extra array of pointers to hold the pointers you need, and then point them to the data. Change your alloc to something like:
int **alloc(int * buf, int r, int c)
{
int **temp = (int **)malloc(sizeof (int *)* r);
for (int i = 0; i<r; i++)
temp[i] = buf + i*c;
return temp;
}
then you call it like:
int **p = alloc(buffer, 4, 4);
you also need to free up the extra buffer.
This way your data and the pointers you need to access it are kept separate and you can keep your original 1D data contiguous.
Note that you don't need to cast the result of malloc in c, in fact some say that you shouldn't.
Also note that this method removes all of the requirement for casting pointers, anything that removes the need for a cast is a good thing.
I think that your fundamental problem is a misconception about 2D arrays in C (Your code is C, not C++).
A 2D array is a consecutive memory space , and the size of the inner array must be known in advance. So you basically cannot convert a 1D array into a 2D array unless the size of the inner array is known at compile time. If it is known, you can do something like
int *buffer=(int *)malloc(sizeof(int)*100);
typedef int FourInts[4];
FourInts *p = (FourInts *)buffer;
And you don't need an alloc function, the data is already aligned correctly.
If you don't know the size of the inner array in advance, you can define and allocate an array of arrays, pointing into the 1D buffer. Code for that:
int ** alloc(int * buf, int r, int c)
{
int **array2d = (int **) malloc(r*sizeof(int *));
for(int i=0; i<r; i++)
array2d[i] = buf+i*c;
return array2d;
}
void _tmain()
{
int *buffer=(int *)malloc(sizeof(int)*100);
int **p = alloc(buffer,4,4);
p[0][3]=10;
p[2][3]=10;
p[3][2]=10; //fails here
printf("\n %d", p[2][3]);
free(buffer);
free(p);
}
But it would have been easier to simply build an array of arrays without using the buffer. If you could use C++ instead of C, then everything could be easier.
If you already have a 1D block of data, the way to make it accessible as a 2D array is to create an array of pointers - one for each row. You point the first one to the start of the block, the next one is offset by the number of columns, etc.
int **b;
b = malloc(numrows*sizeof(int*));
b[0]=temp; // assuming temp is 1D block
for(int ii=1; ii<numrows;ii++)
b[ii]=b[0]+ii*numcols;
Now you can access b[i][j] and it will point to your original data. As long as number of rows and columns are known at run time this allows you to pass variable length 2D arrays around. Remember that you have to free the vector of pointers as well as the main data block when you are done or you will get a memory leak.
You will find examples of this if you google nrutil.c - this is derived from the trick Numerical Recipes in C uses.
This function prototype should be:
void alloc(int *buf[][], int r, int c) //buf[][] <=> **buf, but clearer in this case
{
//*(buf[i]) =
...
}
If you want to work on the same array you have to pass a pointer to this 2D array (*[][]).
The way you do it now is just working on a copy, so when you return it's not modified.
You should also initialize your array correctly :
p = malloc(sizeof(int *[]) * nb of row);
for each row
p[row] = malloc(sizeof(int []) * nb of col);
I want to allocate a 2-D array in C at runtime. Now this can be achieved in the conventional manner like this:
int *matrix[rows]
for (row = 0; row < rows; ++row) {
matrix[row] = (int *)malloc(ncol*sizeof(int));
}
But I found another method, which does the same thing:
int (*p)[rows];
p=(int (*)[rows])malloc(rows*cols*sizeof(int));
Can anyone explain how the 2nd declaration works? Specifically, what is meant by (int (*)[rows])malloc? To the best of my knowledge, malloc is used like (int *)malloc(ncol*sizeof(int)) or (char *)malloc(ncol*sizeof(char)).
Here, you cast malloc's return value to the type pointer to array rows of int.
By the way, in C, the cast of a pointer to void to a pointer to object is not requiered, and even useless. You should not worry about these details. The following code works indeed as well.
#include <stdlib.h>
int (*p)[rows];
p = malloc(rows * cols * sizeof(int));
These are not equivalent, the first allocates an array of pointers to integers, the second allocates an array of integers and returns a pointer to it, you just allocate several next to each other therefore allowing a second dimension to the 'array'.
A simpler version if you don't need the array after the end of the function would be:
int matrix[rows][cols];