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.
Related
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.
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.
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.
#include <stdio.h>
#include <string.h>
int * bin(char a);
int main(void){
char a='a';
int k=0;
int *binary;
binary=bin(a);
for(k=0; k<8; k++){
printf("%d", *binary++);
printf("\n");
}
return 0;
}
int *bin(char a){
int i=0;
int *arr;
int output[8];
char c=a;
for (i = 0; i <8 ; ++i) {
output[8-i-1] = (a >> i) & 1;
}
arr=&output[0];
// for (i = 0; i <8 ; ++i) {
// printf("%d", output[i]);
// }
// printf("\n");
return arr;
}
The ouptut should be the binary value of the char 'a'which is:
0
1
1
0
0
0
0
1
but i got this instead:
0
-1216804320
-1218095335
-1216804320
10
-1076423592
-1218208721
-1216804320
Is this a pointer problem?
How do i fix it so it would print the right answer? thx!!
You're returning a pointer to a local variable (arr), whose contents are no longer valid when the function returns. Use malloc instead:
int main(void){
...
int *arr = bin(a);
...
free(arr);
return 0;
}
int *bin(char a){
int *arr = malloc(8 * sizeof int);
...
return arr;
}
First error I can notice is Scope problem, that you are returning address of local variable output[8];
arr=&output[0];
return arr;
That is wrong, scope of output[] is inside bin() function only.
You should allocate memory for output[] dynamically if you want to access it outside bin() function, like:
int *output = calloc(8, sizeof(int));
even you don't need extra variable just return output from bin()
I have corrected you code like below without much change:
int *bin(char a){
int i=0;
int *output = calloc(8, sizeof(int));
for (i = 0; i <8 ; ++i) {
output[8-i-1] = (a >> i) & 1;
}
return output;
}
Notice removed unused variables c and arr
additionally, don't forgot to free dynamically allocated memory explicitly:
Second (Notice) be aware of Memory Clobbering Error because you are updating binary variable by ++ in printf function.
Just simple don't free(binary); it will produce run time error because you are modifying binary variable inside printf *binary++: first save return address in a extra pointer variable then free that. Like I am doing:
b = binary=bin(a);
// loop
printf("%d", *binary++);
// ^ changing binary variable to point new memory location
// after loop
free(b);
If you free(binary) then it would be wrong because you would free a memory location that is not allocated dynamically because your are changing binary variable.
get a working code here, read comments.
I'm trying to write a little matrix program. Using doublke pointers doesnt work so I figure the easiest way is to have a struct that has the #rows and #columns and a 1d array as the matrix.
But there is some error in the initiation of the matrix as i get:
weird values for the indices (0,0) and (0.1) instead of 0.
Something with this perhaps:
matrix *mtrx = malloc(sizeof(matrix));
mtrx->m = malloc(r * c * sizeof(int));
matrix.c:
#include <stdio.h>
#include <stdlib.h>
#include "Matrix.h"
matrix *alloc_matrix(int r, int c)
{
matrix *mtrx = malloc(sizeof(matrix));
mtrx->m = malloc(r * c * sizeof(int));
if (mtrx == NULL || m == NULL) {
printf("Out of memory.");
exit(1);
}
mtrx->rows = r;
mtrx->columns = c;
return mtrx;
}
void free_matrix(matrix *mtrx)
{
free(mtrx->m);
free(mtrx);
}
void set(matrix *mtrx, int r, int c, int v)
{
(mtrx->m)[r * mtrx->columns + c] = v;
}
int get(matrix *mtrx, int r, int c)
{
return (mtrx->m)[r * mtrx->columns + c];
}
void print_matrix(matrix *mtrx)
{
int i,j;
printf("\n");
for(i=0; i<mtrx->rows; i++) {
for(j=0; j<mtrx->columns; j++) {
printf("%i ", get(mtrx,i,j));
}
printf("\n");
}
}
matrix.h:
struct matrix_ {
int rows;
int columns;
int *m;
};
typedef struct matrix_ matrix;
matrix *alloc_matrix(int r, int c);
void free_matrix(matrix *mtrx);
void set(matrix *mtrx, int r, int c, int v);
int get(matrix *mtrx, int r, int c);
void print_matrix(matrix *m);
main.c:
#include <stdio.h>
#include <stdlib.h>
#include "Matrix.h"
int main(void)
{
matrix *m = alloc_matrix(3,4);
print_matrix(m);
printf("\nm[0][0] = %i", get(m,0,0));
set(m,0,0,0);
printf("\nm[0][0] = %i", (m->m)[0]);
printf("\nm[0][0] = %i", (m->m)[12]);
return 0;
}
output:
all elements except (0,0) and (0,1) is 0.
Function malloc allocates a block of memory, returning a pointer to the beginning of the block. It doesn't set all its bits to zero.
Allocating a block of memory and initializing all its bits to zero - that's what calloc function is for.
Or you can explicitly set these bits to zero by using memset
The object allocated by malloc has an unspecified value. If needed, you have to zero-ize the object yourself (for example using memset function) or call calloc instead of malloc.
malloc() is not guaranteed to zero the memory. Use calloc() to allocate memory with zeros.
malloc does not initiate with 0's (because of performance issues... it's not always what you want)...
use calloc() instead.
malloc does not zero out allocated memory. If you want to fill the matrix with zeros on allocation, use calloc instead. In your case, replace:
mtrx->m = malloc(r * c * sizeof(int));
with
mtrx->m = calloc(r*c, sizeof(int));
Answering your follow-up question:
However is there any difference in efficiency between malloc+memset and calloc? or is calloc simplye malloc+memset?
Typically, for "small" allocations calloc is equivalent to malloc + memset. For "large" allocations (multiple pages, at least), your library may do something more clever relying on some amount of OS support. One approach would be for the OS to lazily zero fill the allocated pages as they are actually used, rather than zero filling all of them immediately upon allocation.
That is correct. The C specification does not say arrays are initilized to anything. You just get a piece of memory that will have whatever values there where before.
You can easily initialize to sero though: memset(mtrx->m, 0, sizeof(int) * r * c);