Reputation: 30926
I have tried this code!I can't understand how it works.
int main()
{
char *s1;
s1=malloc(sizeof(char)*20);
strcpy(s1,"main");
printf("%s\n",s1);
func(s1);
printf("After call %s\n",s1);
return 0;
}
void func(char *s2)
{
//free(s2);<--------------(this is what I'm talking about)
s2=malloc(sizeof(char)*25);
strcpy(s2,"func");
printf("fun---%s\n",s2);
}
Output:
main
fun---func
After call main
But if in func() I add the commented line output is
Outout:
main
fun---func
After call main
I want to know how the whole thing works. I mean s1
is char*
. After allocating it points to a chunk of memory. In C everything is pass by value. So when we pass it there will another variable created in the local scope of (stack) main
that holds the address of the chunked memory (i.e., s1
contains this same value).
s1
in main()
. As s1
is never changed.printf()
after calling the function func()
.Is this the correct idea? If not please clear the concept. In Windows it gave the result as I have told you. But in Linux it was somehow reflecting the change.
What am I missing?
Upvotes: 2
Views: 3750
Reputation: 881553
You're (mostly) correct.
Freeing s2
(and hence s1
) in the function then using s1
on return to main()
is what's known as undefined behaviour.
You shouldn't do it because the standard mandates that pretty much anything is allowed to happen and, here's the rub, that "anything" includes the possibility that it will work.
Why it's working is almost certainly because no-one else has allocated that memory block again and overwritten the data in it, so it still contains what was originally in there.
If, in your main()
between the call to func()
and the printing of s1
, you inserted:
char *s3 = malloc(10000);
strcpy (s3, "Yoohoo, I'v changed");
then you may well find that printing s1
will give you a different result.
Or, since it's UB, maybe not :-)
It's advisable to avoid undefined behaviour even if it seems to work. Changing your compiler, or compiler flags, or order of the code, or even compiling on a blue moon, may change how your code works in unexpected ways.
If you want to pass back a pointer allocated in a function (other than by just using return
), you can use double indirection:
void allocStr (char **pStr) {
free (*pStr);
*pStr = malloc (1000);
}
:
char *xyzzy = NULL;
allocStr (&xyzzy);
This is how you do pass-by-reference in C.
Upvotes: 5
Reputation: 409176
(This doesn't answer your question, but it's to much to put in a comment.)
To make it work without undefined behavior you need to pass the pointer by reference (or rather, since it's not possible in C you have to emulate pass by reference semantics). This can be done by passing a pointer to the pointer, then you can change it in the function.
Something like
void func(char **s2); // Pointer to pointer
int main(void)
{
char *s1 = malloc(20); // No need for `sizeof` as `sizeof(char)` is always 1
strcpy(s1, "main");
func(&s1); // Note use of `&` address-of operator
}
void func(char **s2)
{
free(*s2); // Note use of dereference operator `*`
*s2 = malloc(20);
strcpy(*s2, "func");
}
Upvotes: 3
Reputation: 19
The whole thing works exactly as you said. The reason you didn't get garbage on the second run when dereferencing a stale pointer (s2 pointing to freed memory) is, that the system just hadn't reused the memory yet.
Upvotes: 0