Basic issue with C double pointers (matrices) - c

I am relatively new to programming in general, and I'm trying to write some code to work with square matrices. Unfortunately, I'm stuck very early in the development, as the code
typedef struct Matrix_t{
float** content;
size_t size;
} Matrix_t;
int main(int argc, char** argv) {
Matrix_t* matr;
initMatrix(matr,s);
/*
...
...
...
*/
return 0;
}
void initMatrix(Matrix_t* m, size_t s) {
int i;
m = (Matrix_t*) malloc(sizeof(Matrix_t));
m->content = (float**) malloc(s*sizeof(float*));
for(i=0;i<s;i++){
m->content[i] = (float*) malloc(s*sizeof(float));
}
m->size = s;
}
would SIGSEGV immediately after initMatrix() is done.
Using the debugger, I found out that basically all matrix info is lost after initMatrix() is closed. Why is it? And how can I fix it?
Thanks in advance.

Make matr=NULL in main function and so, try:
main(){
Matrix_t *matr=NULL;
/*Declare and initialize "s" variable.... */
initMatrix(&matr,s); /* See below... */
/*
.....
*/
}
Use a pointer to pointer in Matrix_t *m in function initMatrix
void initMatrix(Matrix_t **m, size_t s)
{
Matrix_t *aux=(Matrix_t*)malloc(sizeof(Matrix_t));
/*check if matrix already allocated */
if(*m != NULL)
{
/*Make a free matrix function to free the matrix before use*/
free_my_matrix(m);
*m=NULL;
}
/***
Work with aux....
aux->content=...malloc....
***/
/* make your base pointer be aux */
*m=aux;
}

You're modifying only a local automatic variable m in your function. C is a pass-by-value language. If you want to pass by address, then an address is what you have to pass, declaring the formal parameter as a pointer-to-type, even when that type is already a pointer and what you're modifying is the the pointer itself.
When you're passing something as an in/out or out parameter, If you find yourself doing this:
void foo(Type *p)
{
p = malloc(...)
}
you're not modifying the data pointed to by p, you're modifying p itself, and the caller will be unaware of the change. The address stored in p upon entrance is lost. Where as this:
void foo(Type *p)
{
*p = ....
}
is modifying what p points to. That said, if Type is already a pointer-type, and what you want to modify it the pointer itself, you must do this:
void foo(Type **pp) // declare a pointer-to-pointer-to-type
{
*pp = malloc(....) // dereference to store the address returned from malloc
// in the pointer pointed to by pp
}
Therefore, the most immediate fix is to declare the formal parameter as a pointer-to-pointer-to-type, passing the address of matr from main()
void initMatrix(Matrix_t **pp, size_t s)
{
int i;
Matrix_t *m = malloc(sizeof(Matrix_t));
m->content = malloc(s*sizeof(float*));
for(i=0;i<s;i++)
m->content[i] = malloc(s*sizeof(float));
m->size = s;
*pp = m; // note: saving pointer to the output target
}
int main(int argc, char** argv)
{
Matrix_t* matr = NULL;
initMatrix(&matr,s); // note: passing address of pointer
/*
...
...
...
*/
return 0;
}
I left out the error checking (or I should say, I didn't add any, as there was none there to begin with) and removed the unneeded casts from malloc, which you can read more about here.
There are about a half-dozen ways to do this, but this is the most direct to what code you already have. I would advise either returning the allocation from the function itself as the ret-val, or not even dynamic-allocating the structure itself as there is no need to do so. Both of which I leave for you to think about.
Best of luck.

Related

Malloc within function not changing pointer value

So when I pass a data type like a struct to assign some memory to it I find that the pointer doesn't change within the main scope. This further becomes a problem when I try to free the memory but obviously if its using the original pointer it will be pointing at the stack address.
void allocate(int *value){
value = malloc(10 * sizeof(int));
}
int main(){
int val2;
allocate(&val2);
free(&val2);
return 0;
}
I can fix this by using a double pointer to be passed into the allocate function but some course work I'm doing requires to only pass a pointer and I cant get it to update the pointer when it returns to main. I have looked around for a while but cant find a straight forward answer, I feel like my coursework is wrong but that might be my lack of understanding.
The requirement to "only pass a pointer" seems contrived, and you could argue that a pointer to pointer (not a "double pointer") is a pointer, but perhaps you could use void * to punch a hole in the type system. Or use a struct:
#include <stdlib.h>
#include <stdio.h>
struct intbuffer {
int *d;
size_t cap;
};
void *
xmalloc(size_t s)
{
void *r = malloc(s);
if( r == NULL ){
perror("malloc");
exit(1);
}
return r;
}
void
allocate(void *p, size_t s)
{
*(int **)p = xmalloc(s * sizeof(int));
}
void
allocate2(struct intbuffer *p)
{
p->d = xmalloc(p->cap * sizeof *p->d);
}
int
main(void)
{
int *val2;
struct intbuffer v;
allocate(&val2, 10);
free(val2);
v.cap = 10; /* Horrible api!! */
allocate2(&v);
free(v.d);
return 0;
}
Note that setting the capacity in the struct prior to making the call to allocate is a violation of many principles of software design, but this whole thing is absurdly contrived due to the bizarre artificial limitations.
There are not enough *'s in each place, but you will have to figure out what that means.
void allocate(int** value){
*value = malloc(10 * sizeof(int));
}
int main(){
int* val2;
allocate(&val2);
free(val2);
return 0;
}

Are the following ways to implement allocation/deallocation functions correct?

In my notes the following code is provided as an example of a programm to allocate and deallocate
memory that doesn't work because the vett variable in the allocate function is local. The function is fixed by using a double pointer and doing the changes in the commented code
void allocate(double *vett, int n) //void allocate(double **vett, int n);
{ printf("vett=%p\n",vett); // printf("vett=%p\n",*vett);
vett = (double*)calloc(n,sizeof(double)); //*vett = (double*)calloc(n,sizeof(double));
printf("vett=%p\n",vett); // printf("vett=%p\n",*vett);
}
void freeit(double *vett) { free(vett); }
int main(int argc,char **argv)
{
double *v=NULL;
int i, size=atoi(argv[1]);
allocate(v,size); // allocate(&v,size);
printf("v=%p\n",v); //printf("v=%p, &v=%p\n",v,&v);
for(i=0;i<size;i++)
v[i]=i;
for(i=0;i<size;i++)
printf("v[%d]=%f\n",i,v[i]);
freeit(v);
return 0;
}
My question is do we really need a double pointer to fix the code? I came up with the following solution:
void* allocate(double *vett, int n) // I changed here
{ printf("vett=%p\n",vett);
vett = (double*)calloc(n,sizeof(double));
printf("vett=%p\n",vett);
return vett; // I added this
}
void freeit(double *vett) { free(vett); }
int main(int argc,char **argv)
{
double *v=NULL;
int i, size=atoi(argv[1]);
v=allocate(v,size); // I changed here
printf("v=%p\n",v);
for(i=0;i<size;i++)
v[i]=i;
for(i=0;i<size;i++)
printf("v[%d]=%f\n",i,v[i]);
freeit(v);
return 0;
}
Is my solution ok? If it is, is any of the solutions preferable over the other?
Additionaly in the following site https://aticleworld.com/dangling-pointer-and-memory-leak/ I found the following functions, but I don't think the Memory_Allocate function is correct, since it returns a local variable ( pvHandle). Am I right?
static unsigned int Allocate_Counter = 0;
static unsigned int Deallocate_Counter = 0;
void *Memory_Allocate (size_t size)
{
void *pvHandle = NULL;
pvHandle = malloc(size);
if (NULL != pvHandle)
{
++Allocate_Counter;
}
else
{
//Log error
}
return (pvHandle);
}
void Memory_Deallocate (void *pvHandle)
{
if(pvHandle != NULL)
{
free(pvHandle);
++Deallocate_Counter;
}
}
int Check_Memory_Leak(void)
{
int iRet = 0;
if (Allocate_Counter != Deallocate_Counter)
{
//Log error
iRet = Memory_Leak_Exception;
}
else
{
iRet = OK;
}
return iRet;
}
Your second example is correct, in the case you return back a pointer, that pointer is the one received from calloc(). And in that case there's no need for the double pointer. In the first case, without returning the pointer with return, the problem is that the pointer you pass to the function is copied in, and the copy can be modified inside the function, but that copy is different than the value of the variable you got it from.
Now two hints:
I have told you this in a comment to the question but: NEVER cast the result of malloc() and friends. You hide several possible errors if you cast the value returned: if you forget to #include <stdlib.h> the compiler will assume the function returns an int (wrongly, a pointer and a int are not the same size in 64bit architectures, and getting a 32 bit value will truncate your data to 32 bits, to later extend it to 64) and will generate code for getting an int that will be converted to a pointer (because of the cast, wrong again) with no warning from the compiler (because you have said with the cast don't worry, I know what I'm doing)
You return a void * from your function, which returns the value of a variable that is of type double *, and do so without a cast, that illustrates how the void * can be automatically converted by the compiler, so making the cast from malloc() totally unnecessary. But why don't return instead a double *, as you have already made the effort to convert a void * into a double *, just to convert it back to void *. If you want a wrapper function to return arrays of doubles, then return a double * in the function, and then you'll avoid the type conversion you do in the return statement, just to convert it again back to double * (which I guess this is what you want).
This applied to your code results in these comments:
/* return void *? Why did you convert it to double *? */
void* allocate(double *vett, int n)
/* why pass a pointer if you are not using the value inside the function body? */
{ printf("vett=%p\n",vett); /* well you print it :$ */
/* don't cast the automatic conversion, let the compiler do its work */
vett = (double*)calloc(n,sizeof(double));
printf("vett=%p\n",vett);
return vett; /* the double * stored in vett is converted to a void * to return it */
}
void freeit(double *vett) { free(vett); }
int main(int argc,char **argv)
{
double *v=NULL;
int i, size=atoi(argv[1]);
v=allocate(v,size); /* and you convert it again to double * here */
printf("v=%p\n",v);
...
so you get a void *, cast it to double * to be stored in a pointer variable, convert it to void * again to return the value to main and convert it again automatically to store it in main's v variable. My conclusion from this sample is that you never cast the value of malloc, and you should use the type void * as low as possible. The standard library functions do it for reasons out of scope, and trying to emulate them is something you can try, but when you have a better understanding of pointers. Until then, better never use void * pointers. A general principle is that you should the proper types, you never had to cast them. Casting should not be necessary (and it's almost never done in well written code) so better avoid casting as much as you can. The 80% of the errors come from bad casts, and the other 20% come from improperly defined types. C is already a language too lazy in type management, don't make it more by overusing of casts.
In my opinion, your code should be:
double *allocate_doubles(int n)
{
/* automatic conversion is done here only */
double *vett = calloc(n, sizeof(double));
printf("vett=%p\n", vett);
/* no conversion as vett is already of the function return type */
return vett;
}
void freeit(double *vett)
{
free(vett);
}
int main(int argc, char **argv)
{
double *v = NULL; /* use spaces, for readability */
int i, /* this is more readable */
size = atoi(argv[1]);
/* and no conversion because both, allocate and v are the same type */
v = allocate(v, size);
printf("v=%p\n", v);
for(i = 0; i < size; i++)
v[i] = i;
for(i = 0; i < size; i++)
printf("v[%d]=%f\n", i, v[i]);
freeit(v);
return 0;
}

Why dynamically allocated memory of a function parameter is lost when exiting the function? [duplicate]

This question already has answers here:
How do I modify a pointer that has been passed into a function in C?
(7 answers)
Closed 8 years ago.
I want to make a function in C that would dynamically allocate memory for a pointer in parameter of the function.
#include <stdio.h>
#include <stdlib.h>
int allocate(char * arr, int size){
int code = -1;
arr = malloc(size);
if(arr != NULL) code = size;
return code;
}
void main(){
char * array;
if(allocate(array,4) != -1){
printf("allocated!\n");
if(array == NULL) printf("Oops it actually didn't allocate!\n");
}
}
When I execute the program; it will only display "allocated!" and "Oops it actually didn't allocate!". That means the memory allocation did happen (because the return code of the function is not -1. But then when I check if array is equal to NULL; it actually is!
This is a programming problem that I've had and sadly in some cases I can't use a workaround like this char * allocate(char * arr, int size); and assigning the return value to char * array.
You lack a level of indirection, you need char**.
Excuse the bad formatting, I write from my phone.
Char* array, array is bound to a memory slot (that will contain a value that points to another memory slot that would be interpreted as a char).
So you copy that value to the function and modify that value locally in allocate, but the modification never reaches the outside scope.
#include <stdio.h>
#include <stdlib.h>
int allocate(char ** arr, int size){
int code = -1;
*arr = malloc(size);
if(*arr != NULL) code = size;
return code;
}
void main(){
char * array;
if(allocate(&array,4) != -1){
printf("allocated!\n");
if(array == NULL) printf("Oops it actually didn't allocate!\n");
}
}
Not done C in something like 10 years but it should be OK.
You can allocate memory inside your function and return the address as shown below
There are also changes like instead of void main it should be int main()
#include <stdio.h>
#include <stdlib.h>
char *allocate( int size){
char *arr;
arr = malloc(size);
return arr;
}
int main(){
char * array;
if((array = allocate(4)) != NULL){
printf("allocated!\n");
}
return 0;
}
Arguments to functions in C are passed by value. This means following function has no sense:
void f(int x) {
x = 1;
}
int y = 0;
f(y);
// y is still 0
When f is invoked, y is copied to x. Any change to x changes that copy and won't affect y. To work around this, you need to either use return value or pass a pointer to y:
void f(int* x) {
*x = 1;
}
int y = 0;
f(&y);
// y is now 1
Here x is still a copy (of a pointer) but it points to y. Changes to x wont be visible outside that function. But changing *x modifies y.
The same rules apply to pointer arguments. You just need one more * for arguments you want to modify:
int allocate(char** arr, int size) {
*arr = malloc(size);
}
char *ptr;
allocate(&ptr);
Also note that checking array for NULL isn't sufficient here, because a locally defined variable could contain garbage value (thus, not being NULL). You have to assign NULL to it before the allocation:
char *array = NULL;

how to return 1000 variables from a function in C?

How to return 1000 variables from a function in C?
This is an interview question asked which I was unable to answer.
I guess with the help of pointers we can do that. I am new to pointers and C can anyone give me solution to solve this problem either using pointers or different approach?
Pack them all in a structure and return the structure.
struct YourStructure
{
int a1;
int b2;
int z1000;
};
YouStructure doSomething();
If it's 1000 times the same type (e.g. int's):
void myfunc(int** out){
int i = 0;
*out = malloc(1000*sizeof(int));
for(i = 0; i < 1000; i++){
(*out)[i] = i;
}
}
This function allocates memory for 1000 integers (an array of integers) and fills the array.
The function would be called that way:
int* outArr = 0;
myfunc(&outArr);
The memory held by outArr must be freed after use:
free(outArr);
See it running on ideone: http://ideone.com/u8NX5
Alternate solution: instead of having myfunc allocate the memory for the integer array, let the caller do the work and pass the array size into the function:
void myfunc2(int* out, int len){
int i = 0;
for(i = 0; i < len; i++){
out[i] = i;
}
}
Then, it's called that way:
int* outArr = malloc(1000*sizeof(int));
myfunc2(outArr, 1000);
Again, the memory of outArr must be freed by the caller.
Third approach: static memory. Call myfunc2 with static memory:
int outArr[1000];
myfunc2(outArr, 1000);
In that case, no memory has to be allocated or freed.
Array Pointer approach:
int * output(int input)
{
int *temp=malloc(sizeof(int)*1000);
// do your work with 1000 integers
//...
//...
//...
//ok. finished work with these integers
return temp;
}
Struct pointer approach:
struct my_struct
{
int a;
int b;
double x;
...
//1000 different things here
struct another_struct;
}parameter;
my_struct * output(my_struct what_ever_input_is)
{
my_struct *temp=malloc(sizeof(my_struct));
//...
//...
return temp;
}
This is how you do it in C.
void func (Type* ptr);
/*
Function documentation.
Bla bla bla...
Parameters
ptr Points to a variable of 'Type' allocated by the caller.
It will contain the result of...
*/
If your intention wasn't to return anything through "ptr", you would have written
void func (const Type* ptr);
instead.

Why I've allocated a pointer memory in a function, but it's also NULL?

The code confused me.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
void create_int(int *p)
{
p = (int *) malloc(sizeof(int));
}
int main()
{
int *p = NULL;
create_int(p);
assert(p != NULL); /* failed. why? I've allocated memory for it. */
return 0;
}
You are not passing the pointer value back from the function. Try:
void create_int(int **p) {
*p = (int *) malloc(sizeof(int));
}
int main() {
int *p = NULL;
create_int(&p);
assert(p != NULL); /* failed. why? I've allocated memory for it. */
return 0;
}
The variable p in the function create_int is a copy of the variable p in main. So any changes made to p in the called function does not get reflected in main.
To make the change get reflected in main you need to either:
Return the changed value:
int* create_int(int *p) {
p = malloc(sizeof(int));
// err checking
return p:
}
...
// in main:
p = create_int(p);
Or pass the address of p as:
void create_int(int **p) {
*p = malloc(sizeof(int));
// err checking
}
...
// in main:
create_int(&p);
You need a pointer to a pointer like this:
void create_int(int **p)
{
*p = (int *) malloc(sizeof(int));
}
int main()
{
int *p = NULL;
create_int(&p);
assert(p != NULL); /* failed. why? I've allocated memory for it. */
return 0;
}
As folks have pointed out, it's failing since you're not actually changing the pointer that the caller has.
A different way to think about the code might be to notice that it's basically wrapping malloc(), i.e. it's doing a memory allocation but with intelligence added. In that case, why not make it have the same prototype (=call signature) as malloc()? That makes it clearer in the caller's context what's going on, and easier to use:
int * create_int(void)
{
return malloc(sizeof (int));
}
int main(void)
{
int *p = create_int();
assert(p != NULL);
return 0;
}
Also, in C you should never cast the return value of malloc() (see Do I cast the result of malloc?).
You need to send a pointer to a pointer to be able to assign a memory to it via a function
void create_int(int **p)
{
*p = (int*)malloc(sizeof_int));
}
int main()
{
int* p = NULL;
create_int(&p);
assert(p != NULL);
return 0;
}
Your code contains two pointers: one in the create_int function and another one in main. When you call create_int, a copy of the pointer in main is made and used, then eliminated when the create_int function returns.
So, any changes you did to the copy within create_int remain there and are not propagated back to main.
The only way to propagate changes between functions in C (aside from, obviously, returning new values) is to pass a pointer to the changed values. This way, while the pointer being passed will be copied, the value that it points to will be the same, so changes will apply.
Since you're trying to change a pointer, you need a pointer-to-pointer.
void create_int(int **pp)
{
// this changes the pointer that `p` points to.
*pp = (int *) malloc(sizeof(int));
}
int main()
{
int *p = NULL;
// this sends a pointer to the pointer p in main
create_int(&p);
assert(p != NULL);
return 0;
}

Resources