Freeing a 2-D array in C - c

Please bear with me as this is probably a very simple question but I am very new to C.
I am trying to malloc a specific array and then free it. However, the line:
M = malloc(N*sizeof(double *));
...doesn't work. Can somebody please explain to me why this is not working and what the solution would be? Many thanks in advance.

You should free all positions, not just the first. See this example I have wrote.
As mentioned from #Grijesh, the allocation is also wrong. The example covers allocation too. Moreover, I suggest you not to cast the return of malloc (more).
You have to think the 2D array, as a 1D array, where every cell of it is a pointer to a 1D array. A picture might help:
http://gsamaras.files.wordpress.com/2014/04/array2d-n.png
Here, 1D array that holds the pointers is to the left and every cell of it, points to another 1D array.
How many 1D arrays to the left? As many cells as you have in the left array.
Btw, Nelly I think this is not a silly question, it's something that gets beginners into trouble. ;)
EDIT:
About your new code, you had to have the same definition and declaration for matrix_free, as well as, call it as you should. What's definition, etc. ?? Answer.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#define Nmax 9000
double **makeMatrix(int N);
void free_matrix(double **M,int N);
int main(void) {
int N;
for (N = 2; N < Nmax; N *= 2) {
double **L = makeMatrix(N);
printf("yes \n");
free_matrix(L, N);
printf("woo \n");
}
return 0;
}
double **makeMatrix(int N) {
int i, j;
double **M;
M = malloc(N * sizeof(double *));
for (i = 0; i < N; i++)
M[i] = malloc(N * sizeof(double));
for (i = 1; i < N; i++) {
for (j = 1; j < N; j++) {
M[i][j] = (i) * (j) * M_PI / N;
}
}
return (M);
}
void free_matrix(double **M, int N) {
int i;
for (i = 1; i <= N; i++) {
free(M[i]);
}
free(M);
}
And then I receive the youwho output. :) But, it will stop at a certain point, because NMAX is too big! Not only NMAX is too big, but N grows really fast ( N *=). Have you done the math in a piece of paper? Too big numbers. For example, if I do N +=, then, I can go until NMAX = 9000.
Debug tip:
How do I know in which loop it reaches?
I printed out the counter of the loop, like this
printf("woo %d\n",N);
Of course, if you feel sure for yourself, then I suggest you learning the debugger.

Related

Dynamic memory allocation repetition in C

I am somewhat new to C programming. I have a doubt regarding dynamic memory allocation. The following is a code in the main program for memory allocation.
double **mat=(double**)malloc(sizeof(double*)*n);
mat[0]=(double*)calloc(sizeof(double),n*n);
for(i=1; i<n; i++)
mat[i] = mat[i-1] + n;
mat = create_square_matrix(n);
I want to call the function and create elements in the matrix inside the function. Do I have once again allocation memory inside the function like below or Is there any other method to avoid this tedious memory allocation repetition. Following is the function.
`double** create_square_matrix(int n)
{
int i,j,sum=0;
double **array2=(double**)malloc(sizeof(double*)*n);
array2[0]=(double*)calloc(sizeof(double),n*n);
for(i=1; i<n; i++)
array2[i] = array2[i-1] + n;
for (i = 0; i < n; ++i)
{
for (j = 0; j < n; ++j)
{
sum=sum+j;
array2[i][j]=sum;
}
}
return array2;
}
`
The above function returns the array which is stored in the 'mat' variable. And another question is how do I free the memory of variable 'array2' inside the function after using the return method. I can't free the memory possibly before returning the array. Is there a method to free the memory in the above function.
Your function create_square_matrix allocates memory and then fills it by some values.
Your top piece of code allocates memory, and then calls create_square_matrix which again allocates memory. It is like to mop floors before calling the janitor who also mops floors. You don't need to allocate memory twice. Not only it is unneccessary, in fact it is bad. Since you perform two allocations, the memory from the first one is lost, and there is no way to free it. This is called memory leak. Instead of
double **mat=(double**)malloc(sizeof(double*)*n);
mat[0]=(double*)calloc(sizeof(double),n*n);
for(i=1; i<n; i++)
mat[i] = mat[i-1] + n;
mat = create_square_matrix(n);
you should write
double **mat = create_square_matrix(n);
As mentioned, in C there's no need to cast to/from void*. Also, your calloc is backwards: use N elements for the first argument, sizeof(element) for the second.
I will answer your question, and then suggest a better approach.
You are choosing double ** for your matrix. Even if it weren't square, you know exactly how many pointers and how many doubles you need, and of course how big each type is. So,
double **M = malloc( n * sizeof(double*) + n * m * sizeof(double) );
does the trick, does it not? If sizeof(double*) == sizeof(double) for your machine (probably true), then
double **M = calloc( (1+n) * m, sizeof(double) );
works, too, but less portably. You also get the zeros for free; you'll have trouble finding a machine for which it's not true that double f=0 yields a value for which all bits are zero.
But why define your matrix as an array of pointers? Why not instead define it as an array of doubles?
double *M = calloc( n * m, sizeof(double) );
Better yet, for the past 15 years or so, C has supported variable-length arrays, meaning you can define arrays whose size is determined at runtime. Back in K&R days, you could define an array M[n] unless n was a static constant or enum. If your arrays aren't ginormous -- meaning that for the machine in question they'll fit comfortably on the stack -- you can skip malloc and simply define your matrix by a size determined at runtime.
Even if you can't do that, can typedef one dimension dynamically,
typedef double (x_axis_t)[m];
double x_axis_t *M = calloc( n * sizeof(x_axis_t), sizeof(double) );
which is nice, because then you can access your array as
M[x][y];
Just don't try to use M[x,y], because that's something else altogether.
BTW, since you're new to the game, to use a c99 compiler, the standard command is c99, not cc. See your friendly manual for details. :-)
Using a nice function macro for memory allocation is always a good idea. Unless you have to free memory manually I would leave it to a garbage collector such as libgc. Below is an example. If you don't want to use a garbage collector you can just replace GC_MALLOC with malloc. When you free the array (manually) you must first free the individual rows.
#include <gc/gc.h>
#include <stdio.h>
#include <stdlib.h>
#define NEW_ARRAY(ptr, n) (ptr) = GC_MALLOC((n) * sizeof (ptr)[0])
double **SquareMatrix(int n)
{
double **A;
int i, j;
NEW_ARRAY(A, n);
for (i = 0; i < n; i++) {
NEW_ARRAY(A[i], n);
for (j = 0; j < n; j++) {
A[i][j] = 0.0;
}
}
return A;
}
int main(void)
{
const int n = 5;
double **A;
int i, j;
A = SquareMatrix(n);
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
printf("%5.2f ", A[i][j]);
}
putchar('\n');
}
return 0;
}

fread'ing a binary file into a dynamically allocated C array

Just a quick comment to start: While there are similar threads to this one, I haven't quite been able to find the solution I'm looking for. My problem is the following:
I have 2D arrays of doulbes saved to binary files and I would like to read the binary files (using C code) into a 2D array. Additionally, I need to allocate the memory dynamically as the shape of the arrays will be changing in my application. To get started, I tried the following code:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
int main(){
int N = 10; //number of rows of 2D array
int M = 20; //number of columns
/* first allocate the array */
double **data;
data = (double **)malloc(N*sizeof(double *));
for(unsigned int i=0; i < N; i++) {
data[i] = (double *)malloc(sizeof(double)*M);
}
FILE *ptr;
ptr = fopen("random_real_matrix.dat", "rb");
fread(data, sizeof(data), 1, ptr);
for(unsigned int i=0; i<10;i++){
for(unsigned int j=0; j<20;j++){
fprintf(stderr, "m[%d][%d] = %f\n ", i, j, data[i][j]);
}
}
}
Unfortunately, this code segfaults. I checked to see if I can set the array entries like
d[0][0] = 235;
and that works fine.
Assuming this approach can be fixed, I'm also interested to know if it could be extended to read to an array of double complex's.
Any advice would be greatly appreciated!
Your fread statement is incorrect. It's a common beginner mistake to think that sizeof gets the size of a dynamically allocated array. It doesn't. In this case it just returns the size of a double **. You will need to read in each double in the file and put that into the correct spot in the array.
for (int ii = 0; ii < N; ++ii)
{
for (int jj = 0; jj < M; ++jj)
{
fread(data[ii][jj], sizeof(double), 1, ptr);
// Be sure to check status of fread
}
}
You can do this with a single for loop (or a single fread) but this is probably clearer to read.
Because you allocated each row separately, you can't read into the entire array at once. You need to do it row by row.
for (int i = 0; i < N; i++) {
fread(data[i], sizeof(double), M, ptr);
}

How do I tell a C program to create n arrays, reading n by scanf?

I'd like to create a small program that adds, subtracts, multiplies and does a cross product for vectors.
Therefore I'd like to have the user enter
- the amount of vectors
- the dimension of said vectors
- what exactly he wants to do with the vectors (one of the above mentioned functions)
Since I am quite new to programming maybe I haven't found the correct source yet, in this case I would be grateful for a hint in the right direction (especially what to search exactly, since I am not a native speaker)
My problem:
I don't know how to program the sum function so that it always sums up n vectors (n being the amount of vectors the user entered)
I have a rough idea about the rest of the functions so maybe I won't bother you with this program again but this sum-problem really is a problem for me.
I'm sure the answer is somewhere near but I just don't seem to be able to find it.
So many thanks in advance :)
Simple vector
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef int Type;
typedef struct vector {
size_t size;
size_t capacity;
Type *array;
} Vector;
Vector *vec_make(){
Vector *v;
v = (Vector*)malloc(sizeof(Vector));
v->size = 0;
v->capacity=16;
v->array=(Type*)realloc(NULL, sizeof(Type)*(v->capacity += 16));
return v;
}
void vec_pushback(Vector *v, Type value){
v->array[v->size] = value;
if(++v->size == v->capacity)
v->array=(Type*)realloc(v->array, sizeof(Type)*(v->capacity += 16));
}
size_t vec_size(Vector *v){
return v->size;
}
Type *vec_getArray(Vector *v){
return v->array;
}
void vec_free(Vector *v){
free(v->array);
free(v);
}
int main(){
int n=5;//user input
Vector *a, *b, *c;
int i, sum=0, size;
int *ap, *bp, *cp;
a = vec_make(); b = vec_make(); c = vec_make();
for (i=0; i<n; ++i) {
vec_pushback(a, i+1);//1,2,3,4,5
}
vec_pushback(b, 2);
vec_pushback(b, 4);
vec_pushback(b, 5);
vec_pushback(b, 6);
vec_pushback(b, 10);
ap=vec_getArray(a);bp=vec_getArray(b);cp=vec_getArray(c);
for(i=0;i<a->size;++i){
sum+=ap[i];
}
printf("sum(va)=%d\n", sum);
size=vec_size(b);
for(i=0;i<size;++i)
vec_pushback(c, ap[i]+bp[i]);
printf("va + vb = vc(");
for(i=0;i<size;++i){
printf("%d", cp[i]);
if(i<size-1)
printf(",");
else
printf(")\n");
}
vec_free(a);vec_free(b);vec_free(c);
return 0;
}
Are you using straight C or C++?
Since you want dynamic memory allocation, I'd really recommend C++ since you can use std::vector for your array which is totally straightforward. The C way is not nearly as simple.
http://www.codeguru.com/cpp/cpp/cpp_mfc/stl/article.php/c4027/C-Tutorial-A-Beginners-Guide-to-stdvector-Part-1.htm
This question explains how to malloc a 2-d array Using malloc for allocation of multi-dimensional arrays with different row lengths basically you start by allocating an array of n int pointers then you loop over that array and do array[i] = (int*)malloc(sizeof(int) * lenght))
Putting that into more a step by step how to;
1) allocate an array of int pointers - int** array = malloc(sizeof(int*) * n);
you use ** because your first pointer points the the beginning of the array and the array is of type int*, each of these int pointers will point to another array.
2) loop over the array - for (i = 0; i < n; i++)
in C there is no simple way to malloc 2-d arrays. you have to build each row 1 by 1.
3) inside the loop allocate the horizontal array - array[i] = (int*)malloc(sizeof(int) * length)
The question I link to includes some checks to make sure the allocation was successful. I don't know how necessary this is, but it can't hurt.

malloc a char[][]

I am trying to malloc a char to have rows and columns with one letter in each cell. Something similar to int x[i][j] where I have i*rows and j*columns. Basically I want to make this:
|
1
222
33333
4444444
I tried with this code but it gives me an error: assignment makes an integer from pointer without a cast
A=(char**) malloc (5*sizeof(char*));
for(i=0;i<N+2;i++)`{
A[i]=(char*) malloc(7*sizeof(char));
}
for(i=0;i<3;i++){
for(j=0;j<7;j++){
left=3;
right=3;
if((j>=left)&&(j<=right)){
A[i][j]=i;
}
}
left--;
right++;
}
I would go with different approach:
#define STEPS 5
#define ARRAY_SIZE STEPS*STEPS
The size of the array in your case can be easily calculated by the formula above.
Now, you just need to allocate fixed size of bytes, and fill it. That's it. Even more, the version below will simply out-beat your version in simplicity and performance.
int i, j;
char *array;
array = malloc(ARRAY_SIZE);
for (i = 0; i < STEPS; i++)
for (j = 0; j < (i * 2 + 1); j++)
*(array + i * STEPS + j) = i + 1;
Proof.
This compiles fine for me, as long as I add this around your code snippet; note that "A" was declared as being of type "char **". It won't work if you write, say "char A[][]".
#include <stdlib.h>
int main() {
const int N = 10;
int i, j, left, right;
char **A;
/* your code */
return 0;
}

c pointer understanding issue

Please have a look at the following code and tell me where does ***ptr locates ?
i.e. i have a feelings that ***ptr actually locates at ptr[0][0][0]
Am I wrong ? The following is a 3d representation of pointer. where I am trying to assign some characters and later i wanted to test what is the index of ***ptr? will be waiting
#include<stdio.h>
#include<conio.h>
#define row 5
#define rw 3
#define col 10
char ***ptr;
int i,j,k;
void main()
{
clrscr();
ptr=(char *)malloc(row*sizeof(char *));
for(i=0;i<row;i++)
{
*(ptr+row)=(char *)malloc(rw*sizeof(char *));
printf("\t:\n");
for(j=0;j<rw;j++)
{
*(*(ptr+row)+rw)=(char *)malloc(col*sizeof(char *));
if(i==0 && j==0)
{ // *(*(ptr+row)+rw)="kabul";
**ptr="zzz";
}
else
*(*(ptr+row)+rw)="abul";
printf("\taddress=%d %d%d = %s\n",((ptr+row)+rw),i,j,*(*(ptr+row)+rw));
}
printf("\n");
}
printf("%c %d",***ptr,ptr);
getch();
}
First of all, I find your coding style extremely hard to read.
Answering your question, yes, ptr[0][0][0] is a synonym of ***ptr. Thats because a[b] is by definition equal to *(a+b), so ptr[0] is equal to *ptr, etc.
Said that, here is my version of your code:
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#define row 5
#define rw 3
#define col 10
char ***ptr;
int main()
{
int i, j;
ptr = (char***)malloc(row * sizeof(char **));
for(i = 0; i < row; i++)
{
ptr[i]= (char**)malloc(rw * sizeof(char *));
printf("\t:\n");
for(j = 0; j < rw; j++)
{
ptr[i][j] = (char*)malloc(col * sizeof(char));
if (i == 0 && j == 0)
{
strcpy(ptr[i][j], "zzz");
}
else
{
strcpy(ptr[i][j], "abul");
}
printf("\taddress=%p %d,%d = %s\n", ptr[i][j], i, j, ptr[i][j]);
}
printf("\n");
}
return;
}
Note the following changes:
Never write void main in C or C++. And throw away any book that prints it.
The argument of malloc is usually the number of elements times the size of the element. Place special attention to the real type that you intend to use.
The return of malloc is usually cast to the type pointer-to-the-type-of-the-element.
The index in the arrays should be i and j, not row and rw.
Why all the *(ptr + x) stuff? That's why we have the ptr[x] syntax.
You probably want to use strcpy to fill your strings, but difficult to say without explaining the problem.
When you want to printf a pointer, use %p.
If you use malloc, include <stdlib.h>.
Prefer local variables (i, j) to global ones, particularly for loops.
And a few other minor changes here and there...
PS. <conio.h>? Really? Are you still using Turbo-C or what?

Resources