error with the memory in duplicate - c

Hello i have this code and when it reaches the second printf there is an error compiler...i think it's about the pointer *y of the function
#include <stdlib.h>
#include<stdio.h>
int *x,*y;
void duplicate(int*x,int *y,int elem){
int j;
y=(int*)malloc(elem*sizeof(int));
for(j=0;j<elem;j++){
y[j]=x[j];
x[j]=x[j]+1;
}
}
int main(){
int j;
y=(int*)malloc(2*sizeof(int));
*y=10;*(y+1)=50;
duplicate(y,x,2);
printf("the poin y con y[0]=%d and y[1]=%d\n",y[0],y[1]);
printf("the poin y con x[0]=%d and x[1]=%d\n",x[0],x[1]);
return 0;
}

When you allocate memory for y (which is the global x) in function duplicate(), it doesn't update the global x because y is a local variable in duplicate().
You don't need to pass x from main() as it's a global variable. If you do need to pass then pass a pointer to pointer to update it:
duplicate(y,&x,2);
and update the function duplicate() to use *y:
*y=malloc(elem*sizeof(int));
and so on.
Suggestions:
Casting the return value of malloc is dangerous in C.
Don't write variable names as confusing as you did here. x is a global variable but you are passing it to a function but calling y there.
Use a standard signature for main() such as: int main(void).

Your problem is that you change the memory address of the pointer y within the duplicate.
When you pass a pointer to a function, a copy of that pointer is created as a local variable in the function. It still points at the same int, so if you dereference the pointer and change the value of the integer, that new value is retained when you return from the function. However, if you change the memory address that is pointed to, as with malloc, only the local copy of the pointer is changed, and the global variable y still points to some unallocated address which may contain garbage or cause a segmentation fault.
To fix this, you could pass a pointer to a pointer - i.e. int** y, or alternatively you could have duplicate return the new memory address:
int * duplicate(int*x,int *y,int elem){
int j;
y=(int*)malloc(elem*sizeof(int));
for(j=0;j<elem;j++){
y[j]=x[j];
x[j]=x[j]+1;
}
return y;
}
Then in main() call it as:
x = duplicate(y,x,2);
Of course, there is no actual reason to pass the target pointer to the duplicate function, so you can simplify it to this:
int * duplicate(int*x,int elem){
int j;
int *y;
y=(int*)malloc(elem*sizeof(int));
for(j=0;j<elem;j++){
y[j]=x[j];
/* I'm not sure why you have this line here, bug? */
x[j]=x[j]+1;
}
return y;
}
Then call it as:
x = duplicate(y,2);

Related

How does malloc work within wrapper 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 2 years ago.
I have a question dedicated to:
void* malloc (size_t size);
In the regular example that can be found on millions of sites over the internet it's shown that the right way to use malloc is the following:
int main()
{
int* num;
num = malloc(sizeof(int));
*num = 10;
printf("Value = %d\n", *num);
free(num);
return 0;
}
But If I want to allocate memory within a function and use it in main like below, then the only option is to implement the function the following way:
void func_alloc(int** elem, int num_value)
{
*elem = malloc(sizeof(int));
**elem = num_value;
}
int main()
{
int* num;
func_alloc(&num, 10);
free(num);
return 0;
}
I assumed by mistake, that such code as below would work:
void func_alloc(int* elem, int num_value)
{
elem = malloc(sizeof(int));
*elem = num_value;
}
int main()
{
int* num;
func_alloc(num, 10);
free(num);
return 0;
}
Could you please explain or maybe give a link to resource with explanation why does it work only this way?
I really cannot understand why do I need double pointer as an input parameter and why in the other case it comes to "segmentation fault"...
Thank in advance ;)
I assumed by mistake, that such code as below will work.
In C, the arguments are passed by value, when you pass a pointer as an argument of a function, you are passing the value of the pointer, basically a copy of it, not the pointer itself, malloc will change the value of that pointer, but since what you passed was a copy, that is what's changed, not the original pointer, that one remains unchanged.
In the second code snippet, the working code, *elem = malloc(sizeof(int)); broadly means make this pointer elem point to this valid memory address given to me by malloc(assuming it succeeds), the value of the pointer to the pointer elem which you passed as an argument remains unchanged, it being a copy doesn't matter because it's not changed, it's still the same address that was passed as argument, the address of the pointer num which is now pointing to the memory location given by malloc.
**elem = num_value means store num_value in the address stored in the pointer where elem is pointing to, which is where num is pointing to, which is the new memory block previously given by malloc.
That being said, it's not the only option, you can use a local pointer, return it and assign it to another local pointer in the caller side, this is still a copy, but it's a copy of the changed pointer:
int *func_alloc(int num_value)
{
int *elem = malloc(sizeof *elem); //more idiomatic
if(elem == NULL){ // check for allocation errors
perror("malloc" );
exit(EXIT_FAILURE);
}
*elem = num_value;
return elem;
}
int main()
{
int* num = func_alloc(10);
free(num);
return EXIT_SUCCESS;
}
Footnote:
In the third code snippet, freeing num, given that it is uninitialized is a bad idea, I assume you know as much, nonetheless I thought I'd mention it. This may be the reason for the segfault you experienced, whatever garbage value num has will be assumed to be valid memory address, and free will try to deallocate it, doing this will invoke undefined behavior. If it was NULL, it's a different story, it's well defined behavior (execept in some very old standars). Initializing variables when they are declared is, in most cases, a good idea.
A commented explanation :
void func_alloc(int* elem, int num_value)
{
/* elem points to address gave by malloc, let's say 0x12345678 */
elem = malloc(sizeof(int));
/* at address 0x12345678 you have now your num_value */
*elem = num_value;
/* end of the function. Changes made to parameters passed by value are lost */
}
int main()
{
int* num;
/* num is a pointer to an address you could not have write access to, you actually don't know */
func_alloc(num, 10);
/* As C arguments are passed by value, changes made into the function are lost */
/* You try to free num which is still a pointer to an address you potentially have no access to => SEGFAULT */
free(num);
return 0;
}
EDIT:
Not shown in this example, but it is good practice to always check that pointer returned by malloc is not NULL, otherwise you should exit without trying to assign a value to the pointer.
If you have:
#include <stdio.h>
void foo(int x)
{
x = 9;
}
int main(void)
{
int a = 1;
foo(a);
printf("%d\n", a);
}
you probably don't expect the value of a in main() to change just because foo() assigned to x, right? It doesn't change, because parameters are assigned by value. The variables x in foo(), and a in main() are two different variables.
The same applies in your code. elem in func_alloc() is a different variable from num in main(), and assigning to the former doesn't change the value of the latter. The fact that these two are of type int *, and not e.g. just int, makes no difference in this.
That said, you can also return the pointer you got from malloc(), e.g.
int *alloc_int(int value)
{
int *p = malloc(sizeof(int));
*p = value;
return p;
}
(not that it seems to make much sense for a mere int.)

Can i return address of a variable in a function of return type pointer? [duplicate]

This question already has answers here:
How to access a local variable from a different function using pointers?
(10 answers)
Return a pointer that points to a local variable [duplicate]
(3 answers)
Closed 3 years ago.
I am trying to understand how pointer to a variable and address of a variable works.
When I am writing the following code :
#include<stdio.h>
int* g(void){
int x = 10;
int *p = &x;
printf("%p,%p",p,&x);
return (p);
}
void main(){
int * p = g();
printf("\n%d",*p);
}
Output:
0060FED8,0060FED8
10
Process returned 3 (0x3) execution time : 0.031 s
Both the address and pointer to x gives the same value, but when i am returning address &x instead of pointer p the code doesn't print the value of x anymore:
#include<stdio.h>
int* g(void){
int x = 10;
int *p = &x;
printf("%p,%p",p,&x);
return (&x);
}
void main(){
int * p = g();
printf("\n%d",*p);
}
Warning:
warning: function returns address of local variable [-Wreturn-local-addr]
Output:
0060FED8,0060FED8
Process returned -1073741819 (0xC0000005) execution time : 8.332 s
Can anyone tell me what am I doing wrong?
What you have been observing is an Undefined Behaviour. There is something called Storage Class in C programming language. The variables inside your function int *g(void) has automatic storage class. They have a lifetime and scope of your function. Whenever you get out of your function, the location allocated for your variables (x and *p) will be destroyed.
So, it doesn't make sense to use address of variables with automatic storage class outside their scope, i.e., outside your function (int *g(void)) as the pointer returned will be a dangling pointer.
You can make use of heap dynamic memory to allocate the space if you want to learn or use memory location outside the function scope.
You can also make use of global variable and return memory address of that global variable from your function.
#include <stdio.h>
#include <stdlib.h>
int x = 10;
int *g(void)
{
int *p = &x;
printf("%p,%p\r\n", p, &x);
return (&x);
}
int *heap(void)
{
int *p = malloc(sizeof(int));
*p = 100;
printf("%p\r\n", p);
return p;
}
int main(void)
{
int *p = g();
printf("%d\r\n", *p);
int *p1 = heap();
printf("%d\r\n", *p1);
return 0;
}
Since x isn't allocated memory on the heap with malloc or calloc, it's instead allocated on what's called the stack. The stack is used for primarily local variables. A local variable exists only within the scope it's declared. A scope is in poor man's terms, anything between two sets of matching braces.
int* g(void){
//x is allocated on the stack, since malloc wasn't used
int x = 10;
//p is pointing to x's spot in memory (on the stack)
int *p = &x;
//These addresses are the same, all is well so far
printf("%p,%p",p,&x);
//We return the memory location of x
//However, since this is the end of this scope (this function), any variables on the
//stack from this scope will be deleted, which means by the time we get back to main
//the variable "x" was deleted, so its spot in memory doesn't mean anything
return (&x);
}
Function g has x declared as local variable. This means that x is only seen/available to function where it is declared. Passing pointer of x to main is useless since x is not visible to main() function. It is always bad practice to return using pointer unless necessary.

Passing Null Pointer in Function

This variable num remains at 0. I suspect this is because I am passing in a NULL pointer, but I am constrained to the main (and parameters) as is. How do I adjust the content of the helper function to update num correctly?
int main(void) {
int * num_results = NULL;
int num = 4;
set(num_results, num);
printf(ā€œ%d\nā€, *num_results);
return 0;
}
void set(int * results,num){
num_results = malloc(sizeof(int));
*num_results = num;
}
I'm going to guess what you really mean with your question and try to give a decent answer.
I guess you want to change num_results to be equal to num by passing it to the function set as a pointer, and I can see a few mistakes you've made:
You probably have this in your full code, but don't forget to #include <stdio.h> to use printf() and to #include <stdlib.h> to use malloc()
Your function set() should be declared before main(), you can do this by declaring a prototype before main() or simply defining the set() function before main().
Now let's go to your solution: you want to pass the num_results as a parameter to a function, allocate some memory and assign the address to num_results and then update the value to the one in num.
When you pass an int * as a parameter, I guess you already know that by passing int you are simply giving a copy of what is inside an int variable. This works the same way with an int *, you are not passing a reference to num_results so that you can update the address of the pointer, you are passing a copy of the current address, NULL, which will not be modified. What could be modified is what is inside of the current address, but the current address is NULL, so not can really be modified.
Since you want to allocate memory and assign its address to num_results, you must pass a pointer to a pointer, so you are passing the address of where your int* variable is being kept and where you can actually change it.
This way, your function should look like void set(int ** results, int num) and you should call it with set(&num_results, num), so you are passing a reference to num_results, where you can change the address it points to, currently NULL and then the address returned by malloc().
You'd also have to change the body of your function, because you're now using an int **, you want to assign the new address to *results, because results == &num_results, and assign num to **results, because *results = num_results.
I hope my explanation is not very confusing and hopefully someone can explain it better with another answer or by editing mine. Final code:
#include <stdio.h>
#include <stdlib.h>
void set(int ** results, int num){
*results = malloc(sizeof(int));
**results = num;
}
int main(void) {
int * num_results = NULL;
int num = 4;
set(&num_results, num);
printf("%d\n", *num_results);
return 0;
}
set(num_results, num);
Here NULL is getting passed to results variable in set(), when you allocate memory to results, NULL is getting replaced by valid memory address, but you need to understand it will be held in results variable only as its a local variable to set()
You should either pass address of num_results to set() so that memory allocated in set() is retained in main(), or just allocate memory to num_results in main function then pass it to set() as done below:
#include <stdio.h>
int main() {
int *num_results = NULL;
int num = 4;
num_results = malloc(sizeof(int));
set(num_results, num);
printf("%d\n", *num_results);
return 0;
}
void set(int *results,int num){
*results = num;
}
Another example would be:
#include <stdio.h>
#include <stdlib.h>
void set(int **r, int num);
int main() {
int *num_results = NULL;
int num = 4;
/*num_results = malloc(sizeof(int));*/
set(&num_results, num);
printf("%d\n", *num_results);
return 0;
}
void set(int **results,int num){
*results = malloc(sizeof(int));
*(*results) = num;
}
How do I adjust the content of the helper function to update num correctly?
That seems the wrong question, as your set() function seems intended to copy the value of num elsewhere, not to update num itself.
One of your problems is where to copy it. Presently, you allocate some memory for that dynamically, and copy it there. That's fine as far as it goes, but the pointer to the allocated memory is not conveyed back to the caller. This is because all C functions pass arguments by value, and in particular, your main() passes the first argument of set() by value (a value of type int *). Modifying the function's copy does not affect its caller's copy -- that's what pass-by-value is all about.
You may be overlooking a simple fact: dynamic allocation is not the only way to obtain a valid pointer value, nor even the the most important or common. When you see a pointer, you should not automatically go looking for malloc(). You can very easily get a pointer from an array, but perhaps even more importantly, you can get a pointer value by applying the address-of operator (&).
For your set() function to do work that its caller can see without resorting to global variables or changing its signature, the caller must pass as the first parameter a valid pointer to an object that the caller can access, such as one of its own local variables. The pointer is passed by value so the function gets a copy, but it's a copy: it points to the same object that the caller's pointer did. The set() function can therefore modify the pointed-to object via its copy of the pointer to it.
So suppose your main() declared its own local variable result, an int. What do you suppose it could do with &result?
In your helper function you should refer to the first parameter name results instead of num_results. Your helper function should be like:
void set(int * results, int num){
results = malloc(sizeof(int));
*results = num;
}
Your code won't compile. Compiler error messages will tell you how to fix them. Here is a fixed one.
#include<stdlib.h>
#include<stdio.h>
int * num_results = NULL;
void set(int * results, int num){
num_results = malloc(sizeof(int));
*num_results = num;
}
int main(void) {
int num = 4;
set(num_results, num);
printf("%d\n", *num_results);
return 0;
}
For the sake of learning it, you can look at the compilation error messages here and try to fix it by yourself:https://segfault.stensal.com/a/XWfv8rxCJHVtAuRQ
Disclaimer: I built stensal.io as a tool to catch memory issues.

Double Pointers in C and their scope

I have this code:
void alloc2(int** p) {
*p = (int*)malloc(sizeof(int));
**p = 10;
}
void alloc1(int* p) {
p = (int*)malloc(sizeof(int));
*p = 10;
}
int main(){
int *p;
alloc1(p);
//printf("%d ",*p);//value is undefined
alloc2(&p);
printf("%d ",*p);//will print 10
free(p);
return 0;
}
So, I understand that alloc1 just makes a local copy so it's not effecting outside the function the pointer which is given as a parameter.
But what is happening with alloc2?
tl;dr;
And why this alloc1(&p); won't work?
Update
I think i answered my question. The crucial thing is that & makes you a pointer and then a was built to a double pointer bei dereferencing once. Then the double pointer points to the address given be malloc. Finally the address was filled with 10.
And alloc1(&p); would work, but you couldn't derefence the double pointer since it takes a single pointer.
Thanks to all of you
It didn't become a double pointer, in alloc2() you are passing a pointer containing the address of main()'s p. When you dereference it you are actually modifying the address stored in main()'s p. And that's why it's working.
Since there is no pass by reference in c, the only way you can modify a parameter inside a function is by passing a pointer with it's address, for example if you have to pass an integer to a function and the function needs to modify it then you make a pointer using the address of & operator and pass that pointer to the function, example
void
modify(int *pointer)
{
*pointer += 1;
}
int
main(void)
{
int value;
value = 0;
modify(&value);
printf("%d\n", value);
modify(&value);
printf("%d\n", value);
}
would output
1
2
A double pointer is a pointer to a pointer, so you are making a pointer from p in main() which stores the address of p in main(), the pointer itself is stored somewhere, so you are passing the address where the pointer is stored and hence you can modify it's contents from within alloc2().
Note: It's bad style to cast the return valud of malloc(), read more about it here.
It would be clearer if you gave the variables in different functions different names. Since you have multiple variables and arguments named p, and they are distinct from each other, it is easy to confuse yourself.
void alloc2(int** pa2)
{
*pa2 = (int*)malloc(sizeof(int));
**pa2 = 10;
}
void alloc1(int* pa1)
{
pa1 = (int*)malloc(sizeof(int));
*pa1 = 10;
}
int main()
{
int *p = 0;
alloc1(p);
//printf("%d ",*p);//value is undefined
alloc2(&p);
printf("%d ",*p);//will print 10
free(p);
return 0;
}
Apart from renaming the arguments of functions, I've also initialised p in main() to zero (the NULL pointer). You had it uninitialised, which means that even accessing its value (to pass it to alloc1()) gives undefined behaviour.
With p being NULL, alloc1() also receives the NULL pointer as the value of pa1. This is a local copy of the value of p from main(). The malloc() call then changes the value of pa1 (and has no effect on p in main(), since it is a different variable). The statement *pa1 = 10 sets the malloced int to be 10. Since pa1 is local to alloc1() it ceases to exist when alloc1() returns. The memory returned by malloc() is not free()d though (pa1 ceases to exist, but what it points to doesn't) so the result is a memory leak. When control passes back to main(), the value of p is still zero (NULL).
The call of alloc2() is different, since main() passes the address of p. That is the value of pa2 in alloc2(). The *pa2 = (int *)malloc(sizeof(int)) statement does change the value of p in main() - to be the value returned by malloc(). The statement **pa2 = 10 then changes that dynamically allocated int to be 10.
Note also that the (int *) on the result of malloc() is unnecessary in C. If you need it, it means one of
You have not done #include <stdlib.h>. The type conversion forces the code to compile, but any usage of the int - strictly speaking - gives undefined behaviour. If this is the case, remove the int * and add #include <stdlib.h>.
You are compiling your C code using a C++ compiler.

Double pointers are also sometimes employed to pass pointers to functions by reference

" Double pointers are also sometimes employed to pass pointers to functions by reference "
can somebody can explain me the above statement, what exactly does point to function by reference means ?
I believe this example makes it clearer :
//Double pointer is taken as argument
void allocate(int** p, int n)
{
//Change the value of *p, this modification is available outside the function
*p = (int*)malloc(sizeof(int) * n);
}
int main()
{
int* p = NULL;
//Pass the address of the pointer
allocate(&p,1);
//The pointer has been modified to point to proper memory location
//Hence this statement will work
*p=10;
//Free the memory allocated
free(p);
return 0;
}
It means that you have a function that takes a pointer pointer (type int ** for example). This allows you to modify the pointer (what data it is pointing to) much in the way passing a pointer by reference would allow.
void change (int *p) {*p = 7;}
void Really_Change (int **pp) {*pp = null;}
int p = 1;
int *pp = &p;
// now, pp is pointing to p. Let's say it has address 0x10;
// this makes a copy of the address of p. The value of &p is still 0x10 (points to p).
// but, it uses that address to change p to 7.
change(&p);
printf("%d\n", p); // prints 7;
// this call gets the address of pp. It can change pp's value
// much like p was changed above.
Really_Change(&pp);
// pp has been set to null, much like p was set to 7.
printf("%d\n", *pp); // error dereference null. Ka-BOOM!!!
So, in the same way that you can pass a pointer to an int and change the value, you can pass a pointer to a pointer and change its value (which changes what it points to.)
I'll try to explain with both code and plain english :). The explanation may get long, but it will be worth the while.
Suppose we have a program, running its main() function, and we make a call to another function that takes an int parameter.
Conceptually, When you pass a variable as a parameter to a function, you can do so in (roughly speaking) two ways: by value, or by reference.
"By value" means giving the function a copy of your variable. The function will receive its "content" (value), but it won't be able to change the actual variable outside its own body of code, because it was only given a copy.
"By reference", on the other hand, means giving the function the actual memory address of our variable. Using that, the function can find out the variable's value, but it can also go to that specified address and modify the variable's content.
In our C program, "by value" means passing a copy of the int (just taking int as argument), and "by reference" means passing a pointer to it.
Let's see a small code example:
void foo(int n) {
n = 10;
printf("%d\n", n);
}
int main() {
int n = 5;
foo(n);
printf("%d\n", n);
return 0;
}
What will the output of this program be? 10 10? Nope. 10 5! Because we passed a copy of the int, by value and not by reference, foo() only modified the number stored in its copy, unable to reach main()'s copy.
Now, if we do it this way:
void foo(int* n) {
*n = 10;
printf("%d\n", *n);
}
int main() {
int n = 5;
foo(&n);
printf("%d\n", n);
return 0;
}
This time we gave foo() our integer by reference: it's actual memory address. foo() has full power to modify it by accessing it's position in memory, foo() and main() are working with the same copy, and so the output will be 10 10.
As you see, a pointer is a referece,... but also a numerical position in memory. It's similar to an int, only the number contained inside is interpreted differently. Think of it this way: when we pass our int by reference, we're passing an int pointer by value!. So the same by value/by reference logic can be applied to pointers, even though they already are references.
If our actual variable was not an int, but an int reference (pointer), and we wanted main() and foo() to share the same copy of that reference so that foo() can modifiy it, what would we do? Why of course, we'd need a reference to our reference! A pointer to a pointer. That is:
int n; /* integer */
int* n; /* integer reference(pointer). Stores an int's position in memory */
int** n; /* reference to integer reference, or double pointer.
Stores int*'s memory address so we can pass int*s by reference. */
I hope this was useful.

Resources