Passing double pointer as function argument - c

I simply want to assign a pointer to another pointer via the function (same memory address). My code is below:
#include <stdio.h>
void d(int** a)
{
int* val_ptr = malloc(1);
*val_ptr = 5;
printf("%d\n", *val_ptr);
a = &val_ptr;
}
int main()
{
int* a = NULL;
d(&a);
printf("%d\n", *a);
return 0;
}
Output from Link
5
Segmentation fault

Your code has three problems:
Here int* val_ptr = malloc(1);, you allocate 1 byte rather than allocating space for an int. Use the following to fix it:
int* val_ptr = malloc(1 * sizeof(int));
This a = &val_ptr; is not what you want. It changes the local pointer and makes it point to the address of val_ptr. This will not affect the pointer that you've defined in main.
Fix it using
*a = val_ptr;
This way, the pointer in main will also reflect the change and will point to the malloced memory
You should free the allocated memory after its use. Add
free(a);
after the printf in main to free it.

Related

Basic C Memory Allocation [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 1 year ago.
#include <stdio.h>
#include <stdlib.h>
void allocateMem(int *a)
{
a = (int*)malloc(5 * sizeof(int));
}
int main()
{
int *ptr;
allocateMem(ptr);
ptr[0] = 5454;
ptr[1] = 54;
printf("Hi %d\n", ptr[1]);
free(ptr);
return 0;
}
I didn't get any output and error with the code. But if I allocate memory in main function, it actually works.
C function arguments are passed by value. This means that when you pass ptr to allocateMem and then modify it within allocateMem, you're not changing anything about ptr.
You are creating a memory leak, since you can't free the memory you've dynamically allocated as you haven't preserved a pointer to it.
Any argument you want a function to modify external to the function you're calling, you need to pass a pointer to, so if you want to modify a pointer, you need to pass a pointer to a pointer, as #babon has demonstrated with the code in their answer.
Here's the fix:
#include <stdio.h>
#include <stdlib.h>
void allocateMem(int **a)
{
*a = malloc(5 * sizeof(int));
}
int main()
{
int *ptr;
allocateMem(&ptr);
ptr[0] = 5454;
ptr[1] = 54;
printf("Hi %d\n", ptr[1]);
free(ptr);
return 0;
}
To write to a variable in another function, you need to pass a pointer to it. Since the intention here is to write to a pointer, you need to pass the address of the pointer - &ptr.
As an address was passed, the allocateMem() function dereferences a once to hop into the memory location which is to be updated and lays down the address returned by malloc(). When this function returns, main() finds that ptr is pointing to a valid address and writes data inside the allocated memory.
You can return the pointer to the allocated memory (and check the return value), like this:
#include <stdio.h>
#include <stdlib.h>
int *allocateMem(void)
{
return (int*)malloc(5 * sizeof(int));
}
int main()
{
int *ptr;
if( NULL != (ptr = allocateMem()))
{
ptr[0] = 5454;
ptr[1] = 54;
printf("Hi %d\n", ptr[1]);
free(ptr);
}
return 0;
}
The constant number 5 in allocateMem should not be hardcoded, or give it a valuable name.

C language Array modification with Malloc

void helperWithoutMalloc(int *arr) {
arr[0] = 18;
arr[1] = 21;
arr[2] = 23;
}
int main() {
int *data;
helperWithoutMalloc(data);
printf("%d\n", data[0]);
return 0;
}
The above method successfully modify the value of data through the method helperWithoutMalloc(); however, when malloc method is applied; similar way doesn't work. Three value in the data array still zero
void helperNotWorking(int *arr) {
arr = malloc(sizeof(int)*3);
arr[0] = 18;
arr[1] = 21;
arr[2] = 23;
}
int main() {
int *data;
helperNotWorking(data);
printf("%d\n", data[0]);
return 0;
}
I'm just wondering what happen when the line arr = malloc(sizeof(int)*3) is implemented; and makes two code so different?
The main confusion is that : first code regardless of its incorrectness, can still modify the array element while second code, can't modify the array elements; since both functions pass the address of array; and we manipulate the array element through address
Any data structure in C as in any other language must be provided with a memory region where it data could be kept. In your first example you failed to do so. The 'data' pointer does not point to any memory and is initialized. It worked by a chance and you just caused your program to write data somewhere, which happened to be writable. you needed something like the following:
int main() {
int data[3]; // allocate an array for data
helperWithoutMalloc(data);
In the above example the memory was provided by the C array of 3 elements.
In a similar fashion you can use malloc:
int main() {
int *data = malloc(sizeof(int) * 3);
helperWithoutMalloc(data);
Note that the space for data was allocated before calling to the function and passed to it. The function can use pointer (memory address) to access the array elements.
In your second example you did a different mistake. You allocated the space, but you assigned the pointer to the parameter of the function. The pointer in your case was passed to your function by value, therefore it is uni-directional. you can pass it to the function but not backwards. It worked perfectly well inside the function but it did not update 'data', so you cannot access the values after returning from the function. There are few ways to work around it. I.e. you can return your pointer from the function:
int *helper() {
int *arr = malloc(sizeof(int)*3);
...
return arr;
}
int main() {
int *data = helper();
...
or you can use a pointer to pointer to pass to the function:
void helper(int **arr) {
*arr = malloc(...)
(*arr)[0] = 0;
...
}
int main () {
int *data;
helper(&data);
In my opinion, the correct way should be
void NoMalloc(int *arr) {
arr[0] = 18;
arr[1] = 21;
arr[2] = 23;
}
int main() {
int *data = (int *)malloc(sizeof(int) * 3);;
NoMalloc(data);
printf("%d\n", data[0]);
free(data);
return 0;
}
The malloc function allocates some memory and returns a pointer to that allocated memory.
Pointer stores addresses in the memory, and when you define a uninitialized pointer (such as the your first piece of code, int * data;) you don't know where the pointer (data) is pointing and therefore accessing the values stored at the location would often cause Access Violations and should never be used.
As with any other type of C variables, pointers are passed by values when serving as an argument of a function. So data itself would not be modified after calling helperWithoutMalloc or helperNotWorking. The second piece of code does not work because after calling helperNotWorking, the data pointer is still an uninitialized pointer. The numbers you though you have stored in data is actually stored in the modified value of arr in the helperNotWorking function, which does not affect does not point to the same address as data anymore.

Return pointer from a function without defining the variable as static?

#include <stdio.h>
#include <stdlib.h>
int* func();
int main(void) {
int *b = NULL,i;
b = func();
for(i=0;i<7;i++)
{
printf("%d\n",*b);
b++;
}
}
int * func()
{
int *p;
p = malloc(sizeof(int) * 7);
int arr[]={1,2,3,4,5,6,7}; //without using static
p = arr;
return p;
}
How to return the address of the array to the main function for printing the values ?? Without declaring the array as static if we allocate memory for the array in heap then can we able to pass the array to the function as a pointer ??
You are close, but not quite there.
The following expressing causes p to point to arr's address which is not the intended effect:
p = arr;
Remember, p is a pointer, and if you do not use the dereference operator *, then you are refering to the pointer's address rather than its value. arr's memory is deallocated when the function exits, and the memory malloc'd to p is lost because you reassigned the address of p to point to the address of the local variable arr.
The solution is to copy the values of arr to p using a for loop:
int i = 0;
for (; i < 7; ++i) {
p[i] = arr[i];
}
This will print the desired result because you replaced the values of what p pointed to rather than the address of p itself.
You can't. The array is gone when you leave the function, any pointer to the array would have an undeterminate value when you leave the function, and using such a pointer in any way invokes undefined behaviour.
Your malloc () call is pointless and leads to a memory leak, because you allocate space for 7 ints on the heap, and then overwrite the pointer, so the memory can never be used or freed.

a simple pointer code

#include <stdio.h>
int main(void)
{
int* a;
*a=20;
printf("%i\n",*a);
return 0;
}
I have the code above. when the code in runtime, I always get the error message "filename.exe has stop working". Why?
You did not allocate any memory for the pointer to point at. You can do so like this:
int *a = malloc(sizeof(*a));
or like this:
int value;
int *a = &value;
If you allocate with malloc then you'll want to call free on the pointer when you are finished using it.
Accessing an uninitialized pointer leads to undefined behaviour. In your program it led to segmentation fault, one very common outcome of uninitialized pointer access.
In int* a; a's default value is garbage, and points to an invalid memory, you can't assign to that. And assignment like *a=20; this is causes an undefined behavior at run time. (syntax wise code is correct so compiled) you may some time get a seg-fault too.
either do:
int i;
int *a = &i; // a points to a valid memory that is i
*a = 20;
or with dynamic memory allocation using calloc() or malloc() functions.
int *a = malloc(sizeof(int));
*a = 20;
Remember dynamic allocated memories we have to deallocate (free) explicitly when we have done with that.
You have wild pointer, either assign memory to it using malloc
int* a = malloc(sizeof(int));
or use a stack variable
int b = 0;
int *a = &b;
*a=20;
The problem is in your assignment
*a = 20.
You can't allocate a value to a pointer variable like that.
int b = 20;
a = &b;
Thanks,
Santhosh

Scope of malloc used in a function

When a function returns, is the memory allocated via malloc freed? Or can it still be accessed in the main() function using pointers?
eg.
void function(int *a)
{
a=(int *)malloc(sizeof(int));
*a=10;
}
int main()
{
int *num;
function(num);
printf("%d",*num);
return(0);
}
Can the integer stored in a be accessed by main() here?
No, the memory allocated with malloc is not freed when you leave the scope/return from the function.
You're responsible for freeing the memory you malloc.
In your case though, the memory is NOT accesible in main(), but that's because you only deal with a local variable.
void function(int *a)
{
a=(int *)malloc(sizeof(int));
Here, a is a local variable within function . Pointers are passed by value in C, so a receives a copy of the pointer in main when you do function(num); main() does not see that you assign to that local copy of the pointer.
You have to do either:
void function(int **a)
{
*a= malloc(sizeof(int));
**a=10;
}
int main()
{
int *num;
function(&num);
printf("%d",*num);
free(num);
return(0);
}
or
int* function(void)
{
int *a= malloc(sizeof(int));
*a=10;
return a;
}
int main()
{
int *num;
num = function();
printf("%d",*num);
free(num);
return(0);
}
malloc()ed memory is only freed when you call free() on it. It can be accessed by anybody with a valid pointer to it until that time.
No. You are passing the pointer numby value, hence the changes made by the function will not be reflected in main. So effectively there is no way to access/free the allocated memory from main
To fix this you can pass the address of num or return a from function and collect the returned value in num
Memory is not freed. Any function can allocate memory and any other can deallocate it. It's a real mess if you're not super-finicky, until... someone invented the Garbage Collection.
malloc is working fine (though you will have to call free() on the pointer it returns). The problem here is that you aren't returning a pointer to the memory it allocated.
"int * a", your parameter to function() is the address of an integer. The usual way to return that would be to rewrite your function as follows:
int * function()
{
int * a = (int *)malloc(sizeof(int));
*a = 10;
return a;
}
To return it via a parameter, you need to return the address of the pointer:
// pp points to a pointer
void function( int ** pp )
{
// Assign allocated memory to the thing that pp points to
*pp = (int *)malloc( sizeof( int ) );
// Get the thing pp points to -- a pointer.
// Then get the thing which THAT pointer points to -- an integer
// Assign 10 to that integer.
**pp = 10;
}
void main()
{
int * p = NULL;
function( & p );
printf( "%d\n", *p );
free( p );
}
And now you know why they invented C#.
Here's a way to rewrite your allocation thing so it's more clear:
void function( int ** pp )
{
int * newmemory = (int *)malloc( sizeof( int ) );
// Assign 10 to the integer-sized piece of memory we just allocated.
*newmemory = 10;
// Assign allocated memory to the thing that pp points to.
*pp = newmemory;
}
You can store the direct address of the allocated memory in a list container then create a function to loop, access each address into a free function, and then pop out the address. You can insert the address directly into the free function like free(myaddresslist.front()); myaddresslist.pop_front(); . This is a quasi way of doing your own garbage collection without having to change your entire project to GC based languages. Use myaddresslist.size() to make sure you don't call free() on an empty field (resulting in a crash) and to determine the number of loops to take.

Resources