realloc

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • CBFalconer

    #31
    Re: realloc

    Michael Knaup wrote:[color=blue]
    >[color=green]
    >> However, in general would the restrict qualifier afford
    >> protection? I am envisioning something like:
    >>
    >> char *s2, s1[SIZE] = "some nonsense";
    >>
    >> s2 = strchr(s1, 'n');
    >> ... obscurative code ...
    >> if ((strlen(s1) + strlen(s2)) < SIZE) cat(s1, s2)[/color]
    >
    > The function cat concatenatiats two "heap" strings allocated by
    > malloc or realloc. You cannot usage cat with an static array as
    > you did. So there is no real need for an size information as long
    > as s1 and s2 are (0 terminatet) C strings.[/color]

    I gave the prototype for the cat I was discussing as:

    char *cat(restrict char *dst, const char *src);

    which in no way restricts the strings to be in memory allocated by
    malloc etc. There is no way, in standard C, to so restrict
    parameters, and any code that requires it is a bomb waiting to
    explode. It is so silly a practice that I never conceived anyone
    would write code requiring it.

    --
    "If you want to post a followup via groups.google.c om, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers." - Keith Thompson


    Comment

    • Al Bowers

      #32
      Re: realloc



      Flash Gordon wrote:[color=blue]
      > Michael Knaup wrote:[/color]
      [color=blue][color=green]
      >>
      >> The function cat concatenatiats two "heap" strings allocated by malloc or
      >> realloc. You cannot usage cat with an static array as you did. So
      >> there is
      >> no real need for an size information as long as s1 and s2 are (0
      >> terminatet) C strings.
      >>
      >> The problem occurs if you do the following with cat
      >> cat (&string, string [+ n]) /* n <= strlen(string) */
      >>
      >> Cause of a reallocation (using realloc on string) in cat. The second
      >> argument may become invalid. A solution for this Problem might be the
      >> following code but im not 100% sure if the test for overlapping is valid
      >>
      >> char* StrConcat (char ** pS0, const char * const s1)
      >> {
      >> char *pTmp = (pS0 ? *pS0 : (pS0 = &pTmp, NULL));
      >>
      >> if (s1) {
      >> register size_t l0 = (pTmp ? strlen (pTmp) : 0u);
      >> register size_t l1 = strlen (s1);
      >> if ((pTmp = realloc (pTmp, l0 + l1 + 1u))) {
      >> /* Check if s1 is part of *pS0 */
      >> if (*pS0 + l0 == s1 + l1) {[/color]
      >
      >
      > If the realloc moves the block then evaluating a pointer in to where is
      > used to be (i.e. *pS0) invokes undefined behaviour. So you need to do
      > this check before the realloc.[/color]

      Yes, this appears to be UB.
      [color=blue]
      >[color=green]
      >> ptrdiff_t d0 = s1 - *pS0;[/color]
      >
      >
      > Again, if the block has been moved by the realloc you are evaluating an
      > invalid pointer invoking undefined behaviour. So you need to work this
      > out before the realloc.
      >[color=green]
      >> memcpy (pTmp + l0, pTmp + d0, l1);
      >> } else {
      >> memcpy (pTmp + l0, s1, l1);
      >> }
      >> pTmp[l0 + l1] = '\000';
      >> *pS0 = pTmp;
      >> }
      >>
      >> }
      >>
      >> return pTmp;
      >> }[/color]
      >
      >
      > How about:
      > #include <stdio.h>
      > #include <string.h>
      > #include <stdlib.h>
      > #include <stddef.h>
      >
      > char* StrConcat (char **pS0, const char *s1)
      > {
      > char *pTmp = (pS0 ? *pS0 : (pS0 = &pTmp, NULL));
      >
      > if (s1) {
      > ptrdiff_t offset;
      > size_t len0 = (pTmp ? strlen(pTmp) : 0);
      > size_t len1 = strlen(s1);
      > int overlapping = 0;
      >
      > /* Check if s1 is part of *pS0 */
      > if (pTmp + len0 == s1 + len1) {[/color]

      (pTmp + len0) has the look of undefined behavior. The flow
      of the code seems to indicate that it is possible for tTmp
      to have the value of NULL. The additition of len0 to pTmp,
      a type char * result, does not appear valid if pTmp
      is a null pointer.
      Perhaps, to make it safe, use:
      if(pTmp && (pTmp + len0 == s1 + len1))
      [color=blue]
      > overlapping = 1;
      > offset = s1 - pTmp;
      > }
      >
      > if ((pTmp = realloc(pTmp, len0 + len1 + 1))) {
      > if (overlapping)
      > s1 = pTmp + offset;
      > memcpy(pTmp + len0, s1, len1);
      > pTmp[len0 + len1] = '\0';
      > *pS0 = pTmp;
      > }
      >
      > }
      >
      > return pTmp;
      > }
      >
      > int main(void)
      > {
      > char *tmp;
      > char *s = NULL;
      > tmp = StrConcat(&s,"o h");
      > printf("%s\n",t mp);
      > s = StrConcat(&tmp, "haha");
      > printf("%s\n",s );
      > return 0;
      > }[/color]

      --
      Al Bowers
      Tampa, Fl USA
      mailto: xabowers@myrapi dsys.com (remove the x to send email)
      Latest news coverage, email, free stock quotes, live scores and video are just the beginning. Discover more every day at Yahoo!


      Comment

      • Chris Torek

        #33
        Re: realloc

        In article <428DE183.4A1FF 383@yahoo.com>
        CBFalconer <cbfalconer@wor ldnet.att.net> wrote:[color=blue]
        >I gave the prototype for the cat I was discussing as:
        > char *cat(restrict char *dst, const char *src);[/color]

        Just an aside (as I think this whole thread is a bit silly :-) ),
        but assuming this is the C99 "restrict", you want to have it
        occur elsewhere in the type:

        char *cat(char *restrict dst, const char *src);

        or more likely:

        char *cat(char *restrict dst, const char *restrict src);

        which matches the C99 strcpy() and strcat() prototypes.

        Note that "restrict" is a constraint on the person using the
        function: compilers need not, and in general cannot, check whether
        the restriction is satisified by any given call.
        --
        In-Real-Life: Chris Torek, Wind River Systems
        Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
        email: forget about it http://web.torek.net/torek/index.html
        Reading email is like searching for food in the garbage, thanks to spammers.

        Comment

        • CBFalconer

          #34
          Re: realloc

          Chris Torek wrote:[color=blue]
          > CBFalconer <cbfalconer@wor ldnet.att.net> wrote:
          >[color=green]
          >> I gave the prototype for the cat I was discussing as:
          >> char *cat(restrict char *dst, const char *src);[/color]
          >
          > Just an aside (as I think this whole thread is a bit silly :-) ),
          > but assuming this is the C99 "restrict", you want to have it
          > occur elsewhere in the type:
          >
          > char *cat(char *restrict dst, const char *src);
          >
          > or more likely:
          >
          > char *cat(char *restrict dst, const char *restrict src);
          >
          > which matches the C99 strcpy() and strcat() prototypes.
          >
          > Note that "restrict" is a constraint on the person using the
          > function: compilers need not, and in general cannot, check
          > whether the restriction is satisified by any given call.[/color]

          Am I correct if I say the restrict simply warns the user that this
          function makes some assumptions about the pointer(s) it is
          receiving, and that it is very likely to go howling off into the
          boondocks if those assumptions are not met? I.e. it has no more
          real effect than a notation in the function documentation.

          --
          "If you want to post a followup via groups.google.c om, don't use
          the broken "Reply" link at the bottom of the article. Click on
          "show options" at the top of the article, then click on the
          "Reply" at the bottom of the article headers." - Keith Thompson


          Comment

          • Flash Gordon

            #35
            Re: realloc

            Al Bowers wrote:[color=blue]
            >
            >
            > Flash Gordon wrote:
            >[color=green]
            >> Michael Knaup wrote:[/color]
            >
            >[color=green][color=darkred]
            >>>
            >>> The function cat concatenatiats two "heap" strings allocated by
            >>> malloc or
            >>> realloc. You cannot usage cat with an static array as you did. So
            >>> there is
            >>> no real need for an size information as long as s1 and s2 are (0
            >>> terminatet) C strings.
            >>>
            >>> The problem occurs if you do the following with cat
            >>> cat (&string, string [+ n]) /* n <= strlen(string) */
            >>>
            >>> Cause of a reallocation (using realloc on string) in cat. The second
            >>> argument may become invalid. A solution for this Problem might be the
            >>> following code but im not 100% sure if the test for overlapping is valid
            >>>
            >>> char* StrConcat (char ** pS0, const char * const s1)
            >>> {
            >>> char *pTmp = (pS0 ? *pS0 : (pS0 = &pTmp, NULL));
            >>>
            >>> if (s1) {
            >>> register size_t l0 = (pTmp ? strlen (pTmp) : 0u);
            >>> register size_t l1 = strlen (s1);
            >>> if ((pTmp = realloc (pTmp, l0 + l1 + 1u))) {
            >>> /* Check if s1 is part of *pS0 */
            >>> if (*pS0 + l0 == s1 + l1) {[/color]
            >>
            >>
            >>
            >> If the realloc moves the block then evaluating a pointer in to where
            >> is used to be (i.e. *pS0) invokes undefined behaviour. So you need to
            >> do this check before the realloc.[/color]
            >
            >
            > Yes, this appears to be UB.
            >[color=green]
            >>[color=darkred]
            >>> ptrdiff_t d0 = s1 - *pS0;[/color]
            >>
            >>
            >>
            >> Again, if the block has been moved by the realloc you are evaluating
            >> an invalid pointer invoking undefined behaviour. So you need to work
            >> this out before the realloc.
            >>[color=darkred]
            >>> memcpy (pTmp + l0, pTmp + d0, l1);
            >>> } else {
            >>> memcpy (pTmp + l0, s1, l1);
            >>> }
            >>> pTmp[l0 + l1] = '\000';
            >>> *pS0 = pTmp;
            >>> }
            >>>
            >>> }
            >>>
            >>> return pTmp;
            >>> }[/color]
            >>
            >>
            >>
            >> How about:
            >> #include <stdio.h>
            >> #include <string.h>
            >> #include <stdlib.h>
            >> #include <stddef.h>
            >>
            >> char* StrConcat (char **pS0, const char *s1)
            >> {
            >> char *pTmp = (pS0 ? *pS0 : (pS0 = &pTmp, NULL));
            >>
            >> if (s1) {
            >> ptrdiff_t offset;
            >> size_t len0 = (pTmp ? strlen(pTmp) : 0);[/color][/color]
            ^^^^^^^^^^^^^^^ ^^^^^^^^[color=blue][color=green]
            >> size_t len1 = strlen(s1);
            >> int overlapping = 0;
            >>
            >> /* Check if s1 is part of *pS0 */
            >> if (pTmp + len0 == s1 + len1) {[/color]
            >
            > (pTmp + len0) has the look of undefined behavior. The flow
            > of the code seems to indicate that it is possible for tTmp
            > to have the value of NULL. The additition of len0 to pTmp,
            > a type char * result, does not appear valid if pTmp
            > is a null pointer.[/color]

            If pTmp is NULL then len0 is 0. Is it legal to add 0 to a NULL pointer?
            [color=blue]
            > Perhaps, to make it safe, use:
            > if(pTmp && (pTmp + len0 == s1 + len1))[/color]

            Yes, that is definitely safe.

            <snip>
            --
            Flash Gordon
            Living in interesting times.
            Although my email address says spam, it is real and I read it.

            Comment

            • Keith Thompson

              #36
              Re: realloc

              CBFalconer <cbfalconer@yah oo.com> writes:[color=blue]
              > Chris Torek wrote:[color=green]
              >> CBFalconer <cbfalconer@wor ldnet.att.net> wrote:
              >>[color=darkred]
              >>> I gave the prototype for the cat I was discussing as:
              >>> char *cat(restrict char *dst, const char *src);[/color]
              >>
              >> Just an aside (as I think this whole thread is a bit silly :-) ),
              >> but assuming this is the C99 "restrict", you want to have it
              >> occur elsewhere in the type:
              >>
              >> char *cat(char *restrict dst, const char *src);
              >>
              >> or more likely:
              >>
              >> char *cat(char *restrict dst, const char *restrict src);
              >>
              >> which matches the C99 strcpy() and strcat() prototypes.
              >>
              >> Note that "restrict" is a constraint on the person using the
              >> function: compilers need not, and in general cannot, check
              >> whether the restriction is satisified by any given call.[/color]
              >
              > Am I correct if I say the restrict simply warns the user that this
              > function makes some assumptions about the pointer(s) it is
              > receiving, and that it is very likely to go howling off into the
              > boondocks if those assumptions are not met? I.e. it has no more
              > real effect than a notation in the function documentation.[/color]

              As I understand it, "restrict" causes certain things to become
              undefined behavior that would not have been undefined behavior in the
              absence of the "restrict". In other words, it gives the compiler
              permission to perform optimizations based on the assumption that those
              things will not occur. It then becomes the programmer's
              responsibility to ensure that the compiler's assumptions are not
              violated. (A conforming compiler could simply ignore "restrict". )

              --
              Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
              San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
              We must do something. This is something. Therefore, we must do this.

              Comment

              • Richard Bos

                #37
                Re: realloc

                Michael Knaup <Michael.Knaup@ iwmh.fraunhofer .de> wrote:
                [color=blue]
                > However, in general would the restrict qualifier afford[color=green]
                > > protection? I am envisioning something like:
                > >
                > > char *s2, s1[SIZE] = "some nonsense";
                > >
                > > s2 = strchr(s1, 'n');
                > > ... obscurative code ...
                > > if ((strlen(s1) + strlen(s2)) < SIZE) cat(s1, s2)[/color]
                >
                > The function cat concatenatiats two "heap" strings allocated by malloc or
                > realloc.[/color]

                Well... the first string must be allocated (or a null pointer), since it
                is realloc()ed. The second string can come from anywhere, as long as
                it's a correct string.

                Richard

                Comment

                Working...