How to deal with matrices in C using dynamic memory allocation? - c

I was trying to run a simulation in which I need to fill three matrices of size "2 x iterations", this is (iterations=)10^8 columns and 2 rows. I also work with a vector t of size 10^8. Using dynamic memory allocation I wrote the following code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#define T 10000
#define dt 0.0001
#define iterations (T/dt)
/*(more code)*/
int main(){
int i, j;
double *t;
double (*x)[2], (*y)[2], (*c)[2];
t=(double *) malloc((iterations-1)*sizeof(double));
x=(double (*)[2]) malloc((2*(iterations))*sizeof(double));
y=(double (*)[2]) malloc((2*(iterations))*sizeof(double));
c=(double (*)[2]) malloc((2*(iterations))*sizeof(double));
for(i=0; i=1; i++){
x[i][0]=50+500*i;
y[i][0]=300;
c[i][0]=15;
}
for(j=0; j<=iterations-2; j++){
t[j+1]=t[j]+dt;
/*(more code)*/
printf("%G %G %G %G %G %G\n",x[0][j+1],x[1][j+1],y[0][j+1],y[1][j+1],c[0][j+1],c[1][j+1]);
}
return 0;
}
Is the dynamic memory allocation correctly written? I mean, do I really have a vector t of size "iterations" and the three matrices of size "2 x iterations"?
And, if I want to fill each component of the matrices, for example I want a 50 in the position (1,4) of the matrix x, then do I have to write x[1][4]=50? (Like in the first "for".)
The problem is that executing the program I get an error: segmentation fault. Then, using a debugger I get the following:
Program received signal SIGSEGV, Segmentation fault.
x[0][0]=50

A generic way to allocate a matrix:
double **mat_init(int n_rows, int n_cols)
{
double **m;
int i;
m = (double**)malloc(n_rows * sizeof(double*));
for (i = 0; i < n_rows; ++i)
m[i] = (double*)calloc(n_cols, sizeof(double));
return m;
}
void mat_destroy(int n_rows, double **m)
{
int i;
for (i = 0; i < n_rows; ++i) free(m[i]);
free(m);
}
You can also do this:
double **mat_init2(int n_rows, int n_cols)
{
double **m;
int i;
m = (double**)malloc(n_rows * sizeof(double*));
m[0] = (double*)calloc(n_rows * n_cols, sizeof(double));
for (i = 1; i < n_rows; ++i)
m[i] = m[i-1] + n_cols;
return m;
}
void mat_destroy2(double **m)
{
free(m[0]); free(m);
}
For both methods above, you can use matrix[row][col] to access a cell. Sometimes, you may prefer to allocate a single array and use matrix[row*n_cols+col] to access a cell.
BTW, I am sure someone will say "don't use cast", but there are benefits of using cast – that is off-topic.

I mean, do I really have a vector t of size "iterations"
t=(double *) malloc((iterations-1)*sizeof(double));
^^^
Since you subtract one, the answer is no.
.... and the three matrices of size "2 x iterations"?
Well - yes you have three matrices of size "2 x iterations". However, what you have is equivalent to:
double m[iterations][2];
so you have "iterations" rows and 2 columns.
Remember to always check for "out of memory", i.e.
p = malloc(....);
if (p == NULL)
{
printf("out of mem\n");
return -1;
}
So you access it like:
m[0][0]
m[0][1]
m[1][0]
m[1][1]
m[2][0]
m[2][1]
m[3][0]
......

Related

How would I free these mallocs?

I have this function to allocate memory to a matrix:
double **mmalloc(int r, int c){
double **matrix = (double **)malloc((r)*sizeof(double*));
for (int y = 0; y < r; y++){
matrix[y] = (double *)malloc(c*sizeof(double));
}
for (int y = 0; y < r; y++){
for(int x = 0; x < c; x++){
matrix[y][x] = 0;
}
}
return matrix;
}
How would I free all the memory of the returned matrix? I have this function to free the matrix... I can free the rows of the matrix but I cant free the columns.
Here's the freeing function:
// Free all memory allocated for A
void mfree(int r, int c, double **A){
for (int y = 0; y < r; y++){
free(A[y]);
}
}
You need to free all rows one by one, then the initially allocated column (that contains all rows)
void xfree(int r, int c, double **A){
for (int y = 0; y < r; y++){
free(A[y]);
}
free (A);
}
in this order.
double ** (Initial allocation)
↓
(double *)row0 → col0 col1 ...
(double *)row1 → col0 col1 ...
...
where each rowi is made of (double) columns.
In order to completely free a dynamically allocated array of arrays, keep these rules in mind
the number of frees has to equal the number of mallocs that was used to allocate the array and its arrays
consider that if something is freed it is not usable anymore, even if it may work by chance (the behavior that follows such action is said Undefined Behavior). For example, if you free(A) first, you shouldn't free(A[i]) since A - a memory space that contains a list of pointers - is not supposed to be allocated/usable anymore.
therefore free first the innermost elements ("contained", eg A[i]) then free the "containers" (eg A).
void xfree(int r, int c, double **A){
for (int y = 0; y < r; y++){
free(A[y]);
}
free(A)
}
I would 'cheat' and just allocate a contiguous block for your data, and then the second block to give you array access to your rows:
int main(){
int r=3;
int c=4;
double* data = malloc(sizeof(double) * r * c);
double** matrix = malloc(sizeof(double*) * r);
int i;
for (i=0;i<r;++i) { /* build the nice syntax accessor */
matrix[i] = &data[i*c];
}
for (i=0;i<(r*c);++i) { /* you can fill/clear the whole matrix in one loop too */
data[i] = i;
}
// access data through matrix as a normal 2d array
matrix[2][2] = 1.1;
int x,y;
for (x=0;x<r;++x) {
for (y=0;y<c;++y) {
printf("[%1.1f]", matrix[x][y]);
}
printf("\n");
}
// when done
free(matrix);
free(data);
return 0;
}
Output:
[0.0][1.0][2.0][3.0]
[4.0][5.0][6.0][7.0]
[8.0][9.0][1.1][11.0]
I don't think it even matters what order you call the two frees (provided you do both and no access in between) since one array just points into the other - you maintain separate references to each.
You could even store data and matrix together in a struct or something and then have a function that takes that struct and frees both areas (or both areas and then the struct itself).
Note: this seemed to compile and work but I don't write C for a living, get a second opinion before using in production code in case I've missed something

correct way to free m*n matrix bidimensional allocation

I allocate a non-square matrix in this way, but I'm not sure if I'm using the deallocation correctly
float **matrix_alloc(int m /* rows */, int n /* columns */)
{
int i;
float **arr = malloc(m*sizeof(*arr));
for(i=0; i<m; i++)
{
arr[i]=malloc(n*sizeof(**arr));
}
return arr;
}
I have tried two way to free the memory
-Attempt A loop rows
void free_mem_mat(int m, float **array) {
int i;
for (i = 0; i < m; i++) {
free(array[i]);
}
free(array);
}
- Attempt B loop columns
void free_mem_mat(int n, float **array) {
int i;
for (i = 0; i < n; i++) {
free(array[i]);
}
free(array);
}
what should I use to free? the way A on the rows or the way B? (I know as written the method is the same I have rewritten this to be most clear possible)
You need one free() for each malloc()*. There were m+1 calls to malloc(); you'd better make m+1 calls to free() too.
Given that as the starting point, option A is the correct solution. However, it is also fair to note that the two functions (option A and option B) are strictly equivalent as long as you pass the m dimension given to the allocation function as the size argument of the deallocation function. The comment in option B is misleading; you're not looping over columns.
Given:
enum { MAT_ROWS = 20, MAT_COLS = 30 };
float **matrix = matrix_alloc(MAT_ROWS, MAT_COLS);
The correct call to free_mem_mat() is:
free_mem_mat(MAT_ROWS, matrix);
* This is an over-simplified statement if you use realloc() or calloc(). You need a free() for each malloc() that was not realloc()'d, and a free() for each realloc() that did not do a free() — by setting the size to 0. Treat calloc() as equivalent to malloc() as far as free() is concerned.
The trouble is that it has many allocations
I prefer this mode
#include <stdio.h>
#include <stdlib.h>
float **matrix_alloc(int m /* rows */, int n /* columns */)
{
int i;
float **arr = malloc(m * sizeof(float *));
*(arr) = malloc(m * n * sizeof(float));
for (i = 0; i < m; i++) {
*(arr + i) = (*(arr) + i * n);
}
return arr;
}
void free_mem_mat(float **array) {
free(*(array));
free(array);
}
int main () {
float **matrix = matrix_alloc(10, 20);
free_mem_mat(matrix);
return 0;
}
more information in:
http://c-faq.com/aryptr/dynmuldimary.html
arr was allocated as an array of m elements, each a pointer to some allocated memory. Therefore, you must free the m pointers in arr. In freeing each, you don't need to mention the size of the thing pointed to.

qsort in C based on a column in 2d array: unexpected behavior

I am trying to sort a 2d array based on a particular column using qsort in C. I am attaching a minimal working code I am using. Essentially I am passing the pointer to the rows of the array to qsort, and based on the column number I want to sort, I modify the element to compare inside the compare function. Now, according to C convention, if I have 2 columns, I expect colnum=0 and colnum=1 to correspond to columns 1 and 2. But, in my implementation, I get the correct result if colnum=1 means column 1 and colnum=2 means column 2. I am stumped as to why this should be ? (I have also included the array allocation function I use).
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "myfun.h"
static int colnum = 0;
int cmp(const void * a,const void * b);
int main(){
int i;
double **z1;
z1=matrix(5,2);
for (i=0; i<5; i++){
z1[i][1]=-i-1; z1[i][2]=16*i+10;
printf("before sort z1 %lf %lf \n",z1[i][1],z1[i][2]);
}
colnum=2;
qsort(z1,5,sizeof(double*),cmp);
for (i=0; i<5; i++){
printf("after sort z1 %lf %lf \n",z1[i][1],z1[i][2]);
}
getchar();
}
int cmp(const void * a,const void * b)
{
double** x = (double**) a;
double** y = (double**) b;
double xval, yval;
xval = *(*(x)+colnum);
yval = *(*(y)+colnum);
printf("%lf %lf \n",xval,yval);
if (xval < yval )
{
return 1;
}
else if (xval > yval)
{
return -1;
}
else
{
return 0;
}
}
double** matrix(int rows,int cols){
int k;
double **m;
m = (double **)malloc(rows * sizeof(double *));
for (k=0; k<rows; k++){
m[k] = (double *)malloc(cols * sizeof(double));
}
return m;
}
Your program has undefined behavior, because your are accessing memory beyond the boundary allocated by your inner allocation loop of matrix():
m = (double **) malloc(rows * sizeof(double *));
for (k = 0; k < rows; k++) {
m[k] = (double *) malloc(cols * sizeof(double));
}
Since cols has the value 2, malloc() only returns memory for 2 elements of type double. But, your code is initializing and reading a non-existing third element instead.
Since doing so is undefined, producing the output you expect is within the realm of possible behaviors. However, it is incorrect since you run the risk of corrupting the heap, and reading invalid data. Running your program under valgrind produces "Invalid write" and many "Invalid read" errors due to this problem in your program.
The correct approach is to store the values in their proper 0 and 1 column indexes in your initialization, set colnum to 1 to sort by the second column, and read from the proper 0 and 1 indexes when you print the array values.
z1 = matrix(5, 2);
for (i = 0; i < 5; i++) {
z1[i][0] = -i - 1;
z1[i][1] = 16 * i + 10;
printf("before sort z1 %lf %lf \n", z1[i][0], z1[i][1]);
}
colnum = 1;
qsort(z1, 5, sizeof(double *), cmp);
for (i = 0; i < 5; i++) {
printf("after sort z1 %lf %lf \n", z1[i][0], z1[i][1]);
}
As a side note, when I was formatting your code for this answer, I noticed that you used an old C anachronism, probably unintentionally:
z1[i][1]=-i-1; /*...*/
The =- construct was the original C's (pre C.89) way of spelling the -= operator. It is highly unlikely you will end up using a compiler that will honor that operator without a diagnostic, but you should be wary of this syntax, and separate the = and the - tokens to remove the ambiguity.
z1[i][1] = -i - 1; /*...*/

"glibc detected" error on c code

I have a problem with a c code i am writing. It has to multiply 2 matrix (filled with randoms integers between 0-9) of a given dimension (mxn multiplied by nxm and the result being an mxm matrix). The matrix are filled by columns. Also i have to output the computing times for both the whole program and the execution of the function that does the calculation.
I am getting an "glibc detected" error while executing the application. I do know that it is due to heap corruption in my program, most likely due to having written outside memory on the malloc'ed arrays by I am unable the find where the error is.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define A(i,j) aa[m*(j)+(i)] //matrix by columns
#define B(i,j) bb[n*(j)+(i)]
#define C(i,j) cc[m*(j)+(i)]
void mmul (int m, int n, double *aa, double *bb, double *cc) {
int i, j, k;
for (i=0; i<m; i++)
for (j=0; j<m; j++) {
C(i,j)=0;
for (k=0; k<n; k++) C(i,j)+=A(i,k)*B(k,j);
}
}
int main (int argc, char *argv[]) {
clock_t exec_timer=clock(), comp_timer;
srand(time(NULL)); //initialize random seed
int m, n, i;
double *aa, *bb, *cc, exec_time, comp_time;
if (argc!=3
|| sscanf(argv[1], "%d", &m)!=1
|| sscanf(argv[2], "%d", &n)!=1
) {
fprintf(stderr, "%s m n \n", argv[0]);
return -1;
}
/* malloc memory */
aa=malloc(m*n*sizeof(int)); //integer matrix
bb=malloc(n*m*sizeof(int));
cc=malloc(m*m*sizeof(int));
/* fill matrix */
for (i=0; i<m*n; i++) aa[i]=rand()%10; //fill with random integers 0-9
for (i=0; i<n*m; i++) bb[i]=rand()%10;
/* compute product */
comp_timer=clock();
mmul(m,n,aa,bb,cc);
comp_time=(double) (clock() - comp_timer) / CLOCKS_PER_SEC;
/* write output */
for (i=0; i<m*m; i++) printf("%i\n",cc[i]);
/* finishing */
free(aa); free(bb); free(cc);
exec_time=(double) (clock() - exec_timer) / CLOCKS_PER_SEC;
printf("exec time = %.3f, comp = %.3f\n", exec_time, comp_time);
return 0;
}
#undef C
#undef B
#undef A
Anyone can see the problem I am missing?
Well, yes, I can see the problem.
You are working with arrays of double, but your allocation code uses int. Since typically a double is twice the size of an int, this leads to horrible amounts of buffer overflow, trashing random memory.
Basically, this:
aa=malloc(m*n*sizeof(int)); //integer matrix
is lying. :) It should be:
aa = malloc(m * n * sizeof *aa); /* Not an integer matrix! aa is double *. */
And the same for the allocations of bb and cc, of course.
Note use of sizeof *aa (meaning "the size of the value pointed at by the pointer aa") to remove the risk of introducing this error, i.e. by not repeating the type manually but instead "locking" it to an actual pointer, you make the code safer.
As a minor note, not related to the problem, you should use const for the read-only arguments to mmul(), like so:
void mmul (int m, int n, const double *aa, const double *bb, double *cc)
That immediately makes it obvious which pointer(s) are inputs, and which is output. It can also help the compiler generate better code, but the main advantage is that it communicates much more clearly what you mean.

How to malloc a 2d jagged array using a pointer passed by reference to a function in C

I have a 2D jagged array declared in my main() block. This is to be passed to a function to have memory allocated to it. The following is the most reduced case which compiles but crashes when it runs. Where am I going wrong?
#include <stdio.h>
#include <stdlib.h>
void alloc2d(double ***p);
int main () {
double **data;
alloc2d(&data);
printf("Before assign to data\n");
data[0][0] = 0.1;
printf("After assign to data\n");
free(data);
}
void alloc2d(double ***p) {
int i, n, m;
// Get some dynamically assigned sizes
printf("Enter size: ");
scanf("%d %d", &n, &m);
// Now allocate
*p = malloc(n * sizeof(double*));
for (i = 0; i < n; i++) {
*p[i] = malloc(m * sizeof(double));
}
printf("End of alloc2d\n");
}
This reads the values but crashes when I enter low numbers (i.e. '1 1') but crashes when I enter high numbers (i.e. '10 10').
You made a very simple syntax error
*p[i] = (double*)malloc(m * sizeof(double));
should really be
(*p)[i] = (double*)malloc(m * sizeof(double));
This is because in C, [] operator has higher precedence than *.
So when you type *p[i],
it is translated into **(p + i).
This means: you are asking the compiler to calculate the address by offsetting the address of p by i * sizeof(double**), which is clearly not what you actually want.
So, in order to force the compiler to dereference p first, simply surroud *p with brackets.
Operator precedence is the answer. *p[i] is equivalent to *(p[i]). This makes you access memory that lies right after the data pointer, which will either corrupt some other variables on the stack, or crash completely.
You were looking for (*p)[i], which will be the i-th entry in the newly allocated array.
What your alloc2d() allocates is not really a 2D array, but:
1 1D n-long array of pointers to double
n 1D m-long arrays of doubles
Multi-dimensional arrays in C are only possible, if all but the last of the dimensions are known at compile-time:
double a[5][11];
Maybe, this program can help you understand... Note, how COLUMNS is a compile-time constant, even if rows is a run-time variable:
#include <stdio.h>
#include <stdlib.h>
#include <sysexits.h>
#include <err.h>
typedef double myrow_t[11]; /* 11 columns */
#define COLUMNS (sizeof(myrow_t)/sizeof(double))
static unsigned
alloc2d(myrow_t **pd)
{
unsigned int rows;
printf("Enter the number of rows: ");
while (scanf("%u", &rows) != 1)
printf("\ninvalid input, please, try again: ");
*pd = malloc(rows * sizeof(**pd));
if (*pd == NULL)
err(EX_TEMPFAIL, "Out of memory");
return rows;
}
int
main()
{
myrow_t *d;
unsigned int row, column, rows;
rows = alloc2d(&d);
for (row = 0; row < rows; row++)
for (column = 0; column < COLUMNS; column++)
d[row][column] = row * column;
for (row = 0; row < rows; row++) {
printf("Row %3d:\t", row);
for (column = 0; column < COLUMNS; column++)
printf("%.0f\t", d[row][column]);
puts("");
}
free(d);
return 0;
}

Resources