In the main function, I just declare double pointer variables and assign 2 dimensional matrix as below.
int main(){
double **XNODE;
XNODE = (double**)calloc(2,sizeof(double*));
for(int i=0; i<2; i++){
XNODE[i] = (double*)calloc(3,sizeof(double));
}
XNODE[0][0] = 1.0; XNODE[0][1] = -1.0; XNODE[0][2] = -122.0;
XNODE[1][0] = 2.0; XNODE[1][1] = 3.0; XNODE[1][2] = -4.0;
test(*XNODE);
return 0;
and then put the XNODE variable in the below "test" function
void test(double*XNODE)
{
for(int i=0; i<2; i++){
for(int j=0; j<3; j++){
printf("%e ", *(XNODE+3*i+j));
}
}
My expectation is
1 -1 -122
2 3 -4
However the output is as below
1 -1 -122
1.63e-322 2 3
How can I fix this problem??
test(*XNODE); passes the pointer saved in XNODE[0]. That pointer's value was from the allocation when (i==0) and XNODE[i] = (double*)calloc(3,sizeof(double));. That allocation has memory for 3 double.
test() attempts to print 6 adjacent double. The first 3 are as expected. The rest are outside the allocation and so undefined behavior (UB).
How can I fix this problem??
Rewrite test() to test(int rows, int cols, double **d).
Re-write test() body to use rows, cols, d.
Pass test(2, 3, XNODE).
The code inside the function, *(XNODE+3*i+j), expects to be able to calculate the location of any array element as an offset from the base pointer, XNODE. To do this, all of the array elements must be in memory consecutively after the start of the array.
The allocations in main do not do this. The loop allocates memory for each row separately, so each row is wherever the calloc routine puts it. They are unlikely to be consecutively in memory.
To allocate memory correctly, you must allocate all of the memory for the elements of the array in one allocation. Calculate that amount of memory, allocate it, and pass the pointer to that memory to test. You can do this with double *XNode = calloc(2 * 3 * sizeof *XNode);.
To access that memory, you can do it the same way the code in test does: The element in row i, column j is *(XNode + 3*i + j). This can also be written XNode[3*i + j].
Related
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 am trying to track down a bug a big program. I think it is due to how I am passing arrays to my functions. Am I doing this correctly?
main(){
int *x = declarArray(x, 100);
int *y = declarArray(x, 100);
// lines of code....
x = arrayManip(x, 100);
// more code...
int i;
for(i=0; i<100; i++)
y[i] = x[i];
//more code...
free(x);
free(y);
}
This is how I manipulate arrays:
int *arrayManip(int *myarray, int length){
int i;
for(i=0; i<length; i++)
myarray[i] = i;
return array;
}
This is how I initialize the arrays:
int* declareArray(int *myarray, int length){
myarray = (int*) malloc(length*sizeof(int*));
if (myarray==NULL)
printf("Error allocating memory!\n");
int i;
for(i=0; i<length; i++)
myarray[i] = -888;
return myarray;
}
This code seems to work fine on a small scale, but maybe there is a problem once I have many more arrays of larger size that are often getting passed back and forth and copied in my program?
declarArray :
Name is not gramatically correct
The name of the function is not what it does
malloc with sizeof(int*), not sizeof(int). Guarantuee to be a bug in 64 bit machine
malloc fails, you print, but still write to null
passing myarray as argument is a noop as is
-888 is a magic number
There is no error check whatsoever
My advice. Throw it away and start fresh
No, as per my understanding.
You allocating one dim array => elements in that array should be integers and not pointers to integers so instead of this :
myarray = (int*) malloc(length*sizeof(int*));
it should be :
myarray = (int*) malloc(length*sizeof(int));
In function arrayManip you pass param named array, and than you trying to access it as myarray
This:
myarray = (int*) malloc(length*sizeof(int*));
allocates an array of length pointers to an integer, but then puts it into a pointer to an integer (i.e. an array of integers, not pointers to integers). If you want an array of integers, you want:
myarray = (int*) malloc(length*sizeof(int));
or (if you want to zero it):
myarray = (int*) calloc(length, sizeof(int));
which does the size x length calculation itself.
To allocate a list of pointers to integers, you want:
myarray = (int**) malloc(length*sizeof(int*));
or
myarray = (int**) calloc(length, sizeof(int*));
Unless you are fantastically concerned about speed, I find using calloc() results in fewer bugs from uninitialized arrays, and makes the reason for the allocated size more obvious.
The pointer is of word size [2 or 4 ,... depending on machine architecture]. whatever it may point to int,double,float,...
for integer pointer it works if it takes 4 bytes for int in machine. when u go for other data type it 'll lead you to error.
you should allot memory as
pointer = (DataType*) malloc (length * sizeof(DataType));
use malloc and to make your code clear.
void* malloc (size_t size);
malloc reference
use memset to allot default value [-888] for your array.
void *memset(void *str, int c, size_t n)
I am trying to make a generic function in C that takes a 2D array of ANY type and copies it into a contiguous memory block. ( I need this function for Aggregate operations on MPI on my complex datatypes).
Imagine I have the following integer array
int n = 5;
int m = 6;
int** int_array = (int**) malloc(n* sizeof(int*));
for (int i = 0; i < n; i++ )
int_array[i] = (int *) malloc(m * sizeof(int) );
In this type of memory allocation one cannot, in principle, hope to access the , say i,j-th entry of int_array using the following pointer arithmetics
int value = (*lcc)[i*m+j];
Therefore I implemented a function that basically allocates a new memory block and neatly orders the entries of int_array so that the above indexing should work.
void linearize(char*** array, int n, int m,unsigned int size_bytes){
char* newarray = (char*)malloc(m*n*size_bytes);
//copy array!
for (int i = 0;i<n;i++)
for(int j = 0;j<m*size_bytes;j++)
{
newarray[i*m*size_bytes+j] = (*array)[i][j];
}
//swap pointers and free old memory!
for (int i = 0;i<n;i++)
{
char * temp = (*array)[i];
(*array)[i] = newarray + i*m*size_bytes ;
free(temp);
}
}
I wanted to make the above function to work with any kind of array type, hence I used char pointers to do operations byte by byte. I tested the function and so far it works, but I am not sure about memory deallocation.
Does free(temp) free the whole memory pointed to by int_array[i], that is the m*sizeof(int) bytes accessible from int_array[i] or only the first m bytes (since it thinks that our array is of type char rather than in) ? Or simply put, "Does the linearize function induce any memory leaks? "
Thank you in advance!
*EDIT*
As suggested by Nicolas Barbey, I ran a valgrind checks for memory leaks and it found none.
So to summarize the main points that I found difficult to understand about the behaviour of the program were:
in the function linearize does the following code induce memory leaks:
char * temp = (*array)[i];
(*array)[i] = newarray + i*m*size_bytes ;
free(temp);
NO!! somehow gnu compiler is smart enough to know how many bytes pointed to by "temp" to free. Originally I was afraid that if I array[i] is a pointer of type int , for example, that points to a memory location with say 5 ints = 5*4 bytes, the free(temp) is going to free only the first five bytes of that memory.
Another point to make is : how to free the already linearized array? that is if you have:
// first initialize the array.
int** array = (int**)malloc(5*sizeof(int*);
for(int i = 0; i< 5;i++)
array[i] = ( int* ) malloc(5*sizeof(int));
//now a call to linearize
linearize(&array,5,5,sizeof(int));
... do some work with array ....
// now time to free array
free(array[0]);
free(array);
//suffices to free all memory pointed to by array[i] and as well as the memory allocated
// for the pointers.
Thanks for the discussion and the suggestions.
You need to call free() exactly one call per malloc() inorder to be no memory leaks. Which means in your case int_array is passed to linearize function allocates a block of memory other than int_array allocation, therefore you need to loop over int_array[i] freeing each int* that you traverse followed by free'ing int_array itself. Also you need to free block created in linearize function too.
Here is a slightly slimmer version using actual two dimensional arrays:
void * linearize(void** array, int n, int m,unsigned int size_bytes){
char (*newarray)[m * size_bytes] = malloc(m*n*size_bytes);
//copy array!
int i;
for (i = 0;i<n;i++) {
memcpy(newarray[i], array[i], sizeof(*newarray));
free(array[i]);
}
free(array);
return newarray;
}
Use:
int (*newarray)[m] = linearize(array, n, m, sizeof(**int_array));
int value = newarray[i][j];
// or
value = newarray[0][i*m + j];
// or
value = ((int *)newarray)[i*m + j];
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().
I created a 2-D matrix using double pointer like that:
int** pt; pt = (int*) malloc(sizeof(int)*10);
I know that a pointer is freed like that
free(ptr);
How can we free the double pointer?
What if we print something and later freed that memory and exit the program? Does the final memory consist of that which we used or it will be same as initial?
Say you have a matrix mat
int** mat = malloc(10 * sizeof(int*));
for (int i=0; i<10; ++i) {
mat[i] = malloc(10 * sizeof(int));
}
then you can free each row of the matrix (assuming you have initialized each correctly beforehand):
for (int i=0; i<10; ++i) {
free(mat[i]);
}
then free the top-level pointer:
free(mat);
For your second question: if you allocate memory and use it, you will change that memory, which will not be "reverted" even if you free it (although you will not be able to access it reliably/portably any more).
Note: the top-level malloc is using sizeof(int*) as you are allocating pointer-to-ints, not ints -- the size of int* and int are not guaranteed to be the same.
If your matrix isn't "ragged", i.e. all rows have the same length, you might want to consider:
Accessing it manually, i.e. just treat it as a 1D array of values, and keep a separate width value. To access an element at (x,y) use mat[y * width + x].
If you really want the convenience of mat[y][x], you can improve it by doing a single call to malloc() that allocates both the pointer array and all the rows, then initializing the pointers to point at each row. This has the advantage that it can all be free:ed with a single free(mat); call.
The second approach would look something like this:
double ** matrix_new(size_t width, size_t height)
{
double **p = malloc(height * sizeof *p + width * height * sizeof **p);
double *e1 = (double *) (p + height);
size_t i;
for(i = 0; i < height; ++i)
p[i] = e1 + i * width;
return p;
}
Note: the above is un-tested, and production code should obviously check for failure before using p.
For the first question, I'll tell you the rule of thumb.
The number of times you call free() should be equal to the number of times you call malloc() + the number of times you call calloc().
So if you allocated in such a way that you made a pointer to pointers to ints, and then used malloc() on each pointer to ints, then you'll free "row" number of times, where each free() is for each pointer to ints.
And a final free() is called on the pointer to pointers to ints. That will balance out the malloc() + calloc() with free() calls.