Problems with allocating memory for a matrix in c - c

I'm trying to allocate memory to a matrix in a function and then print its values.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void cria_ilhas(int** ilhas, int n){
int i, p;
ilhas = (int**) malloc(n*sizeof(int*));
for (i=0;i<n;i++){
ilhas[i] = (int*) malloc(n*sizeof(int));
for (p=0; p<n; p++)
ilhas[i][p] = 4;
}
printf("value %d\n",ilhas[0][0]);
}
void main(){
int n=5, i, j;
int **ilhas;
cria_ilhas(ilhas, n);
for(i=0; i<n; i++){
for(j=0;j<n;j++){
printf("%d ",ilhas[i][j]);
}
printf("\n");
}
}
But this is the output:
value 4
Segmentation fault
Why i'm having segmentation fault?
How can I use memset in this kind of matrix?

You’re doing it almost correctly. When you’re calling cria_ilhas, you’re passing in the variable ilhas, and expecting that when you change it inside of the function, that effects the variable in main, too. Unfortunately, C doesn’t work that way.1
What you’ll want to do is remove the ilhas parameter from cria_ilhas and stop passing it in when you call it in main. Then just declare ilhas as a local variable in cria_ilhas. To get the value back to main, you’ll need to return it from cria_ilhas, and in main, when you call it, assign ilhas to its result.
1 Side note: if you were using C++, you could make it work by changing the parameter from int **ilhas to int **&ilhas.

Change your code to this shape and tell me if it worked
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int** cria_ilhas( int n){
int i, p;
int **ilhas
ilhas = (int**) malloc(n*sizeof(int*));
for (i=0;i<n;i++){
ilhas[i] = (int*) malloc(n*sizeof(int));
for (p=0; p<n; p++)
ilhas[i][p] = 4;
}
printf("value %d\n",ilhas[0][0]);
return ilhas;
}
void main(){
int n=5, i, j;
int **ilhas;
ilhas = cria_ilhas(n);
for(i=0; i<n; i++){
for(j=0;j<n;j++){
printf("%d ",ilhas[i][j]);
}
printf("\n");
}
}
I think it should work for you, your code is much likely to be true but the problem is you have defined a large structure in heap (ilhas definition in main method) and you sent it address to a method ( call by reference) which suppose to allocate memory for it from stack segment but not heap, if you pass the address of a simple type variable to a method, it woundnt be a problem but allocating memory for array's will raise segmentation problem.

Related

Got a message free(): invalid pointer, when running C code

I wanted to allocate memory for a 2d double variable in C, and then free the memory, but got message: "free(): invalid pointer" when running the code.
Any idea where is the problem?
The code is listed below
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
double **allocate_2d_double(int rows_upper_lim, int cols_upper_lim){
//want to allocate arrays starting from 1 to rows_upper_lim, 1 to cols_upper_lim
#define rows_lower_lim 1
#define cols_lower_lim 1
int i, no_of_rows=rows_upper_lim-rows_lower_lim+1,
no_of_cols=cols_upper_lim-cols_lower_lim+1;
double ** a;
a=(double **) malloc(((no_of_rows+1)*sizeof(double*)));
if(!a){
printf("Memory allocation 1 failed in allocate_wts\n");
exit(1);
}
a-=rows_lower_lim;
/* Allocate rows and set pointers to them */
a[rows_lower_lim]=(double *) malloc
(((no_of_rows+1)*(no_of_cols+1))*sizeof(double));
if(!a[rows_lower_lim]){
printf("Memory allocation 2 failed in allocate_wts\n");
exit(1);
}
a[rows_lower_lim] -=cols_lower_lim;
for(i=rows_lower_lim+1; i<=rows_upper_lim; i++)
a[i]=a[i-1]+no_of_cols;
/* Return pointer to array of pointers to row */
return a;
}
void free_2d_double(double **a){
if(a[1]) free (a[1]);
if(a) free (a);
}
int main(void) {
double **tt;
int nn1=2, nn2=3;
int i,j;
tt=allocate_2d_double(nn1, nn2);
for (i=1; i<=nn1; i++){
for (j=1; j<=nn2; j++){
tt[i][j]=i+j;
printf("tt[%d][%d]=%f\n",i,j,tt[i][j]);
}
}
free_2d_double(tt);
return 0;
}
It is hard to understand what your code is doing (for sure not allocating 2D array). If you want to allocate 2D:
void *allocate_2d_double(size_t rows_upper_lim, size_t cols_upper_lim)
{
double (*arr)[cols_upper_lim] = malloc(rows_upper_lim * sizeof(*arr));
return arr;
}
void free_2d_double(void *a){
free (a);
}
int main(void) {
int nn1=2, nn2=3;
double (*tt)[nn2];
int i,j;
tt=allocate_2d_double(nn1, nn2);
for (i=1; i<=nn1; i++){
for (j=1; j<=nn2; j++){
tt[i - 1][j - 1]=i+j;
printf("tt[%d][%d]=%f\n",i-1,j-1,tt[i - 1][j - 1]);
}
}
free_2d_double(tt);
return 0;
}
or better:
int main(void) {
int nn1=2, nn2=3;
double (*tt)[nn2];
int i,j;
tt=allocate_2d_double(nn1, nn2);
for (i=0; i<nn1; i++){
for (j=0; j<nn2; j++){
tt[i][j]=i+j + 2;
printf("tt[%d][%d]=%f\n",i,j,tt[i][j]);
}
}
free_2d_double(tt);
return 0;
}
Remember that indexes in C start from 0 (zero)
The function free requires the memory address that were returned by malloc to be passed to that function.
However, you are modifying the addresses returned by malloc in the following lines:
a-=rows_lower_lim;
and
a[rows_lower_lim] -=cols_lower_lim;
You should not pass these modified addresses to free, as that invokes undefined behavior. Instead, if you must modify these addresses, you may want to remember the original addresses in a separate variable, in order to later pass them to free.

dynamic allocation of 2d array function

So I have a program in C structured in 3 files: main.c, alloc.h and alloc.c. In the main.c function, I have the declaration of a pointer to another pointer to which I intend to alloc an n * m array:
#include <stdio.h>
#include <stdlib.h>
#include "alloc.h"
int main() {
int **mat, n, m;
alloc_matrix(&mat, int &n, int &m);
return 0;
}
In alloc.c I have the following declarations:
#ifndef ALLOC_H_INCLUDED
#define ALLOC_H_INCLUDED
#include <stdio.h>
#include <stdlib.h>
void alloc_matrix(int***, int*, int*);
#endif
In alloc.c I have the function:
void alloc_matrix(int ***mat, int *n, int *m) {
printf("\nn = "); scanf("%d", n);
printf("\nm = "); scanf("%d", m);
*mat = (int**)calloc(*n, sizeof(int*));
int i;
for (i = 0; i < *n; i++)
*(mat + i) = (int*)calloc(*m, sizeof(int));
}
But the program doesn't work. It enters some kind of loop and doesn't end.
If I allocate it in main it would work but I have no idea what I am doing wrong in the alloc function.
Here is the correct code. Your error was that in the definition of alloc_matrix, you used *(mat+i) in the allocation loop, which should be *(*mat+i) as, mat is a int*** so the base address for the 2D array would be in *mat. Then you need to move by offset i and then de-reference that memory location for the 1D array.
Main:
#include <stdio.h>
#include <stdlib.h>
#include "alloc.h"
int main()
{
int **mat,n,m;
alloc_matrix(&mat,&n,&m);
return 0;
}
alloc.h
#ifndef ALLOC_H_INCLUDED
#define ALLOC_H_INCLUDED
#include <stdio.h>
#include <stdlib.h>
void alloc_matrix(int***,int*,int*);
#endif
alloc.c :
void alloc_matrix(int ***mat,int *n,int *m)
{
printf("\nn = "); scanf("%d", n);
printf("\nm = "); scanf("%d", m);
*mat = (int**)calloc(*n,sizeof(int*));
int i;
for(i = 0; i < *n; i++)
*(*mat+i) = (int*)calloc(*m,sizeof(int));
}
The code for the read function :
void read_matrix(int ***mat,int n,int m)
{
int i,j;
for(i = 0; i < n; i++)
for(j = 0; j < m; j++)
{
printf("mat[%d][%d] = ", i, j);
scanf("%d", (*(*mat+i))+j);
}
}
The problem with it is that it only reads the first row and the it freezes.
void alloc_matrix(int ***mat,int *n,int *m)
There are two problems in this line. Neither is fatal but both are worth fixing.
First problem: A matrix in this program is represented as an int**. Why does alloc_matrix accept an int***? All standard functions that allocate something (malloc and friends) return a pointer to that something. This is an idiomatic way of doing things in C. It reduces your star count (being a three-star C programmer is not an achievement to be proud of) and simplifies the code. The function should be changed to
int** alloc_matrix( // but what's inside the () ?
The second problem is, why should a function called alloc_matrix prompt the user and read values? These things are not related to allocation. A function should do one thing and do it well. Does malloc prompts you to enter the size? Does fopen prompt you to enter the filename? These things would be regarded as nonsense of the first degree, and rightly so. It is advised to read the sizes elsewhere and pass them to alloc_matrix as input arguments. Hence,
int** alloc_matrix(int n, int m) { // but what's inside the {}?
What remains of alloc_matrix is simple:
int** alloc_matrix(int n, int m) {
int** mat; // that's what we will return
int i;
mat = (int**)calloc(n, sizeof(int*));
for(i = 0; i < n; i++)
// here comes the important part.
Since we have simplified alloc_matrixand reduced the star count in mat, what should we do with the old body of the loop? It was:
*(mat+i) = (int*)calloc(...);
but if we remove a star, it becomes
(mat+i) = (int*)calloc(...);
which is an obvious nonsense. Perhaps the old line was a problem. The fact that it provoked a compiler warning certainly doesn't speak for its correctness. So how to correct it? There aren't too many options. It turns out that in order to restore sanity, we must leave the old left-hand side (written for the three-star mat) intact. Or, better still, use an equivalent but more idiomatic notation:
mat[i] = (int*)calloc(m, sizeof(int));
So the entire function now becomes
int** alloc_matrix(int n, int m) {
int **mat;
int i;
mat = (int**)calloc(n, sizeof(int*));
for(i = 0; i < n; i++)
mat[i] = (int*)calloc(m, sizeof(int));
return mat;
}
and it should be called like
mat = alloc_matrix(n, m);
It is often said that one should not cast the result of calloc and friends. But in this case the cast has enabled a warning which helped to find a bug. I'm leaving the casts in place for now.
There is another idiom for the allocation that does not require the cast, but also avoids the problem of types not matching.
Instead of using the type for the sizeof, you can use the dereferenced pointer as the type information is available in the variable:
mat = (int**)calloc(n, sizeof(int*));
can be changed to
mat = calloc(n, sizeof *mat); //sizeof is an operator not a function

creating a 2d array using double pointer

i have made a program that creates 2d array.
the code below works well on visual studio & turbo c:
#include<stdio.h>
#include<stdlib.h>
int **allocarr(int **arr, int row, int col){
int i;
arr=calloc(row, sizeof(int));
for(i=0; i<row; i++){
arr[i]=calloc(col, sizeof(int));
}
return arr;
}
void freearr(int **arr, int row, int col){
int i;
for(i=0; i<row; i++) free(arr[i]);
free(arr);
}
void printarr(int **arr, int row, int col){
int i, j;
for(i=0; i<row; i++){
for(j=0;j<col;j++){
printf("\t%d", arr[i][j]);
}
printf("\n\n");
}
}
int main(){
int **arr=NULL;
arr=allocarr(arr, 3, 3);
arr[2][2]=8;
printarr(arr, 3, 3);
freearr(arr,3, 3);
return 0;
}
but it does not work on mac os x gcc and mingw gcc.
everything compiles fine without any warning and errors(-Wall & -Wextra),
but it crashes on runtime...
in gdb and lldb, it says that free() is freeing a non-allocated memory.
after allocating a pointer array, when i allocate memory after that, exactly 2 of the memory block(is this the right word?) will have random values that cannot be initialized.
i tried allocating another array before i assign it to the pointer array.
it prints fine(no 2 random values), but will still occasionally crash when assigning values on it.
why is this happening?
This
arr=(int **)calloc(row, sizeof(int));
should be
arr = calloc(row, sizeof(int*));
(note that the cast is not required in C and actually discouraged)
So on implementations where the size of a pointer is not the size of int (e.g. on x64 machines), you will invoke undefined behavior when you read outside the bounds of allocated memory.
You might consider not using an explicit type as the operand of sizeof.
arr = calloc(row, sizeof*arr);
This lets the compiler deduce the type and will help you avoid errors like this.

C: segmentation fault when running function from another file

When ever i run this code, it works up until i get to the printf statement in my main function, thats when i get a segmentation fault error. so it will run like "enter how many numbers you want" 3 "Enter the numbers in the array" 1 2 3 array[0] = 1 array[1] = 2 array[2] = 3 segmentation error. Can you guys please tell me why im getting this error and how to fix it? thank you
//pathfinder.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Vector.h"
int main()
{
Vector *V;
VectorRead(V);
printf("%d", V->item[0]);
return 0;
}
//Vector.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
typedef struct{
int *item;
int size;
} Vector;
void VectorRead(Vector *V) ;
void VectorRead(Vector *V)
{
int N;
printf("Enter how many numbers you want?\n");
scanf("%d", &N);
V = (Vector *)malloc(sizeof(Vector *) * N);
V->size = N;
V->item = (int *)malloc(sizeof(int *) * V->size);
printf("Enter the numbers that you want in your array\n");
int i = 0;
while(i < V->size && scanf("%d", &(V->item[i++])) == 1);
int j;
for(j = 0; j< V->size; j++){
printf("array[%d]=%d\n", j, V->item[j]);
}
}
This error has nothing to do with your code being in different files.
When you call VectorRead(), you are passing a pointer value. Inside that function, you are setting the local V to the return value of a call to malloc(). There is no way for that local V to return back to the caller.
You will need to do something to return the newly allocated value of V back to the caller. Changing your function to return a Vector * (instead of taking one as a parameter) would be a good approach.
Your local Vector, V, is not being modified when VectorRead() is called. Try instead accepting a Vector ** in your function:
void VectorRead(Vector **V)
and modify the function accordingly.
Or, since your function has no return value, and as #EOF points out in the comments, it is probably a better idea to not take a parameter, and simply return the Vector *:
Vector *VectorRead(void)

Segmentation fault when using malloc for 2D array

I create a 2-D array using malloc. When I use printf to print the array element in for loop, everything is fine. But when I want to use printf in main, these is a Segmentation fault: 11.
Could you please tell me what the problem with the following code is?
#include <stdlib.h>
#include <stdio.h>
void initCache(int **cache, int s, int E){
int i, j;
/* allocate memory to cache */
cache = (int **)malloc(s * sizeof(int *)); //set
for (i = 0; i < s; i++){
cache[i] = (int *)malloc(E * sizeof(int)); //int
for(j = 0; j < E; j++){
cache[i][j] = i + j;
printf("%d\n", cache[i][j]);
}
}
}
main()
{
int **c;
initCache (c, 2, 2);
printf("%d\n", c[1][1]); // <<<<<<<<<< here
}
Since your cache is a 2D array, it's int**. To set it in a function, pass int***, not int**. Otherwise, changes to cache made inside initCache have no effect on the value of c from main().
void initCache(int ***cache, int s, int E) {
int i, j;
/* allocate memory to cache */
*cache = (int **)malloc(s * sizeof(int *)); //set
for (i = 0; i < s; i++) {
(*cache)[i] = (int *)malloc(E * sizeof(int)); //int
for(j = 0; j < E; j++){
(*cache)[i][j] = i + j;
printf("%d\n", (*cache)[i][j]);
}
}
}
Now you can call it like this:
initCache (&c, 2, 2);
You changed a local variable, which won't effect the local variable c in main.
If you want to allocate in the function, why pass a variable? Return it from the function.
int **c = initCache(2, 2);
You could use a return, or else a *** as suggested by others. I'll describe the return method here.
initCache is creating and initializing a suitable array, but it is not returning it. cache is a local variable pointing to the data. There are two ways to make this information available to the calling function. Either return it, or pass in an int*** and use that to record the pointer value.
I suggest this:
int** initCache(int **cache, int s, int E){
....
return cache;
}
main()
{
int **c;
c = initCache (2, 2);
printf("%d\n", c[1][1]); <<<<<<<<<< here
}
====
Finally, it's very important to get in the habit of checking for errors. For example, malloc will return NULL if it has run out of memory. Also, you might accidentally as for a negative amount of memory (if s is negative). Therefore I would do:
cache = (int **)malloc(s * sizeof(int *));
assert(cache);
This will end the program if the malloc fails, and tell you what line has failed. Some people (including me!) would disapprove slightly of using assert like this. But we'd all agree it's better than having no error checking whatsoever!
You might need to #include <assert.h> to make this work.

Resources