pass by value

Discussion in 'C Programming' started by somenath, Sep 19, 2007.

  1. somenath

    somenath Guest

    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
     
    somenath, Sep 19, 2007
    #1
    1. Advertising

  2. somenath

    Army1987 Guest

    On Wed, 19 Sep 2007 02:36:37 -0700, somenath wrote:

    > 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.

    --
    Army1987 (Replace "NOSPAM" with "email")
    If you're sending e-mail from a Windows machine, turn off Microsoft's
    stupid “Smart Quotes†feature. This is so you'll avoid sprinkling garbage
    characters through your mail. -- Eric S. Raymond and Rick Moen
     
    Army1987, Sep 19, 2007
    #2
    1. Advertising

  3. 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>

    --
    Richard Heathfield <http://www.cpax.org.uk>
    Email: -www. +rjh@
    Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
    "Usenet is a strange place" - dmr 29 July 1999
     
    Richard Heathfield, Sep 19, 2007
    #3
  4. On Wed, 19 Sep 2007 02:36:37 -0700, somenath <>
    wrote:

    >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
     
    Barry Schwarz, Sep 19, 2007
    #4
  5. somenath wrote:
    >
    > 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:>
     
    Kenneth Brody, Sep 19, 2007
    #5
  6. somenath

    Guest

    On Sep 19, 5:36 pm, somenath <> wrote:
    > 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".

    > 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.
     
    , Sep 20, 2007
    #6
  7. On Wed, 19 Sep 2007 13:42:23 -0400, Kenneth Brody
    <> wrote:

    >somenath wrote:
    >>
    >> 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
     
    Barry Schwarz, Sep 20, 2007
    #7
  8. Barry Schwarz wrote:
    >
    > On Wed, 19 Sep 2007 13:42:23 -0400, Kenneth Brody

    [... pointer free()d in a function called by this function ...]
    > >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.


    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:>
     
    Kenneth Brody, Sep 20, 2007
    #8
  9. On Thu, 20 Sep 2007 09:49:59 -0400, Kenneth Brody wrote:
    > Barry Schwarz wrote:
    >>
    >> On Wed, 19 Sep 2007 13:42:23 -0400, Kenneth Brody

    > [... pointer free()d in a function called by this function ...]
    >> >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.

    >
    > 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.
     
    =?iso-2022-kr?q?Harald_van_D=0E=29=26=0Fk?=, Sep 20, 2007
    #9
  10. Kenneth Brody said:

    > Barry Schwarz wrote:
    >>
    >> On Wed, 19 Sep 2007 13:42:23 -0400, Kenneth Brody

    > [... pointer free()d in a function called by this function ...]
    >> >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.

    >
    > 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.

    --
    Richard Heathfield <http://www.cpax.org.uk>
    Email: -www. +rjh@
    Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
    "Usenet is a strange place" - dmr 29 July 1999
     
    Richard Heathfield, Sep 20, 2007
    #10
  11. Richard Heathfield wrote:
    >
    > 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:>
     
    Kenneth Brody, Sep 21, 2007
    #11
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jerry
    Replies:
    20
    Views:
    8,039
    Roedy Green
    Sep 9, 2005
  2. venkatagmail
    Replies:
    11
    Views:
    714
    James Kanze
    Oct 3, 2007
  3. Vols
    Replies:
    3
    Views:
    394
    Ian Collins
    Apr 28, 2008
  4. Tricky
    Replies:
    0
    Views:
    607
    Tricky
    Mar 19, 2009
  5. Tricky
    Replies:
    0
    Views:
    1,058
    Tricky
    Mar 19, 2009
Loading...

Share This Page