pass by value

S

somenath

Hi All,

I was trying to understand the pass by value mechanism in c. To
understand it I wrote a
Small code as mentioned bellow.

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void check(char *src);
int main(void)
{
char *s =malloc (10 * sizeof(*s));
strcpy(s,"hi");
printf("\n Value before function call = %s \n",s);
check(s);

printf("\n Value after function call = %s \n",s);
return 0;


}
void check(char *src)
{
free(src);
}

My assumption was it will print "hi " after call of check .
But it is printing

Value before function call = hi

Value after function call =

My understanding is "src" will receive a copy of "s" so if I free
"src" it will not effect "s".
Please let me know if my assumption is correct?
But for second thought
Here in "void check(char *src)" I am freeing memory
Location not obtain by malloc so it may be showing undefined
Behavior .
I am confused .Please provide some inputs.


Regards,
Somenath
 
A

Army1987

Hi All,

I was trying to understand the pass by value mechanism in c. To
understand it I wrote a
Small code as mentioned bellow.

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void check(char *src);
int main(void)
{
char *s =malloc (10 * sizeof(*s));
strcpy(s,"hi");
printf("\n Value before function call = %s \n",s);
check(s);

printf("\n Value after function call = %s \n",s);
return 0;


}
void check(char *src)
{
free(src);
}

My assumption was it will print "hi " after call of check .
But it is printing

Value before function call = hi

Value after function call =

My understanding is "src" will receive a copy of "s" so if I free
"src" it will not effect "s".

free() frees the memory *pointed to by* its argument. And since
src is a copy of s, they point to the same location of memory.
 
R

Richard Heathfield

somenath said:
Hi All,

I was trying to understand the pass by value mechanism in c. To
understand it I wrote a
Small code as mentioned bellow.

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void check(char *src);
int main(void)
{
char *s =malloc (10 * sizeof(*s));
strcpy(s,"hi");

Don't do this until you've assured yourself that the allocation has
succeeded:

if(s != NULL)
{
strcpy(s, "hi");
printf("\n Value before function call = %s \n",s);
check(s);

printf("\n Value after function call = %s \n",s);

Army1987 has already pointed out that it is the value of the pointer that
matters here, not the value stored in any particular object. Calling
free() is like handing a note to the Air Force, telling them which
building to bomb. When you pass a copy of the pointer to check() and thus,
in due course, to free(), it's like passing a high-quality photocopy of a
note to the Air Force. As an indicator of which target to bomb, the
photocopy is just as good as the original. :)
return 0;


}
void check(char *src)
{
free(src);
}

My assumption was it will print "hi " after call of check .
But it is printing

Value before function call = hi

Value after function call =

It could easily have printed what you expected it to print. It could easily
have crashed the program. It could easily have crashed the computer. It
could (less easily) have destroyed your monitor. Where undefined behaviour
is concerned, ISO provides no guarantees.
My understanding is "src" will receive a copy of "s" so if I free
"src" it will not effect "s".

What is s? Just a pointer to the first byte in a memory block that /was/
allocated, until you free()d that memory.

<snip>
 
B

Barry Schwarz

Hi All,

I was trying to understand the pass by value mechanism in c. To
understand it I wrote a
Small code as mentioned bellow.

A poor example to demonstrate the issue at hand. Better is the
example in section 4.8 of the faq (c-faq.com). For the code below,
the key issue is that BY DEFINITION a pointer becomes indeterminate
when the object it points reaches the end of its lifetime.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void check(char *src);
int main(void)
{
char *s =malloc (10 * sizeof(*s));

s now points to allocated memory. The lifetime of allocated memory is
from the time its allocated to the time it is explicitly freed.
strcpy(s,"hi");
printf("\n Value before function call = %s \n",s);
check(s);

check frees the allocated memory. The value in s now becomes
indeterminate. The fact that check received a copy of s and has no
idea where s is physically located in main is irrelevant.
printf("\n Value after function call = %s \n",s);

Even though the actual bits in s probably have not changed, you are
now attempting to evaluate an indeterminate address. This invokes
undefined behavior. (Irrelevant detail: on most systems, this will
result in an attempt to access memory you don't own.) At this point,
anything could happen. On a poorly designed system (tm), it could
produce the same result as the previous printf leading you to believe
that nothing was wrong. On well designed system (tm), your program
would be terminated with some indication of an invalid memory access.
return 0;


}
void check(char *src)
{
free(src);
}

My assumption was it will print "hi " after call of check .
But it is printing

Value before function call = hi

Value after function call =

You received a result in between the two extremes described above.
Consider yourself lucky.
My understanding is "src" will receive a copy of "s" so if I free
"src" it will not effect "s".
Please let me know if my assumption is correct?

Obviously not.
But for second thought
Here in "void check(char *src)" I am freeing memory
Location not obtain by malloc so it may be showing undefined
Behavior .

Why do you say the memory you are freeing is not obtained by malloc?
As noted above, you are invoking undefined behavior but not for this
reason.


Remove del for email
 
K

Kenneth Brody

somenath said:
Hi All,

I was trying to understand the pass by value mechanism in c. To
understand it I wrote a
Small code as mentioned bellow.

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void check(char *src);
int main(void)
{
char *s =malloc (10 * sizeof(*s));
strcpy(s,"hi");
printf("\n Value before function call = %s \n",s);
check(s);

printf("\n Value after function call = %s \n",s);
return 0;

}
void check(char *src)
{
free(src);
} [...]
My understanding is "src" will receive a copy of "s" so if I free
"src" it will not effect "s".
Please let me know if my assumption is correct?
[...]

You are half correct, sort of, in a roundabout way, maybe. (Did I
include enough weasel clauses?)

You are correct that "s" has not been affected. It still contains
the same value as before the call to check(). This would be true
even if check() altered the value of "src".

However, "s" is a pointer, and what it points to has been affected.
Specifically, the memory that it points to has been freed.

So, "s" is still pointing to the same address, but what is at that
address has changed. (Change the "%s" to "%p" to print the pointer
itself, and you will see that the pointer has not changed.)

Note that it is possible for an implementation to behave as you
thought it might. (That is, print "hi" even after freeing the
memory.) However, had it done so, it would merely be a side effect
of free() not having modified the buffer itself. (For example, it
may modify its "hidden" information regarding the heap used by
malloc and friends, without touching the buffers themselves.)

Consider yourself lucky that the library you are using apparently
zeroed out the buffer, allowing you to discover your erroneous
assumption.

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:[email protected]>
 
L

lovecreatesbea...

Hi All,

I was trying to understand the pass by value mechanism in c. To
understand it I wrote a
Small code as mentioned bellow.

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void check(char *src);
int main(void)
{
char *s =malloc (10 * sizeof(*s));
strcpy(s,"hi");
printf("\n Value before function call = %s \n",s);
check(s);

it's same as you've written here

free(s);
printf("\n Value after function call = %s \n",s);
return 0;

}

void check(char *src)
{
free(src);

}

My assumption was it will print "hi " after call of check .
But it is printing

Value before function call = hi

Value after function call =

My understanding is "src" will receive a copy of "s" so if I free
"src" it will not effect "s".

Sure. But you demonstrated it wrongly by displaying what's pointed by
"src".
 
B

Barry Schwarz

somenath said:
Hi All,

I was trying to understand the pass by value mechanism in c. To
understand it I wrote a
Small code as mentioned bellow.

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void check(char *src);
int main(void)
{
char *s =malloc (10 * sizeof(*s));
strcpy(s,"hi");
printf("\n Value before function call = %s \n",s);
check(s);

printf("\n Value after function call = %s \n",s);
return 0;

}
void check(char *src)
{
free(src);
} [...]
My understanding is "src" will receive a copy of "s" so if I free
"src" it will not effect "s".
Please let me know if my assumption is correct?
[...]

You are half correct, sort of, in a roundabout way, maybe. (Did I
include enough weasel clauses?)

You are correct that "s" has not been affected. It still contains
the same value as before the call to check(). This would be true
even if check() altered the value of "src".

However, "s" is a pointer, and what it points to has been affected.
Specifically, the memory that it points to has been freed.

So, "s" is still pointing to the same address, but what is at that
address has changed. (Change the "%s" to "%p" to print the pointer
itself, and you will see that the pointer has not changed.)

But it would still invoke undefined behavior.



Remove del for email
 
K

Kenneth Brody

[... pointer free()d in a function called by this function ...]
But it would still invoke undefined behavior.

Is it UB to simply look at a pointer (w/o dereferencing it) which has
been freed?

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:[email protected]>
 
?

=?iso-2022-kr?q?Harald_van_D=0E=29=26=0Fk?=

[... pointer free()d in a function called by this function ...]
But it would still invoke undefined behavior.

Is it UB to simply look at a pointer (w/o dereferencing it) which has
been freed?

Yes (unless it's NULL), as far as strictly standard C is concerned, the
value becomes indeterminate once it's freed, and you're only allowed to
read indeterminate values if all representations of the type are valid
values.
 
R

Richard Heathfield

Kenneth Brody said:
[... pointer free()d in a function called by this function ...]
But it would still invoke undefined behavior.

Is it UB to simply look at a pointer (w/o dereferencing it) which has
been freed?

Yes.

1.6 of C89:
* Undefined behavior --- behavior, upon use of a nonportable or
erroneous program construct, of erroneous data, or of
indeterminately-valued objects, for which the Standard imposes no
requirements.

4.10.3 of C89: "The value of a pointer that refers to freed space is
indeterminate."

QED.
 
K

Kenneth Brody

Richard said:
Kenneth Brody said: [...]
Is it UB to simply look at a pointer (w/o dereferencing it) which has
been freed?

Yes.

1.6 of C89:
* Undefined behavior --- behavior, upon use of a nonportable or
erroneous program construct, of erroneous data, or of
indeterminately-valued objects, for which the Standard imposes no
requirements.

4.10.3 of C89: "The value of a pointer that refers to freed space is
indeterminate."

QED.

Well, that's pretty clear. Thanks.

Not that I would ever use the pointer after it's been freed (at least,
not on purpose), but I didn't realize that simply looked at the
pointer without dereferencing it would invoke UB. I've used systems
where the debug library will purposely trash the buffer within free(),
but the systems have always kept the address itself valid.

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:[email protected]>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,143
Latest member
SterlingLa
Top