General method for dynamically allocating memory for a string

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

    General method for dynamically allocating memory for a string

    I have searched the internet for malloc and dynamic malloc; however, I still
    don't know or readily see what is general way to allocate memory to char *
    variable that I want to assign the substring that I found inside of a
    string.

    Any ideas?


  • Ben Pfaff

    #2
    Re: General method for dynamically allocating memory for a string

    "smnoff" <343rhinosourue us@hotmail.comw rites:
    I have searched the internet for malloc and dynamic malloc; however, I still
    don't know or readily see what is general way to allocate memory to char *
    variable that I want to assign the substring that I found inside of a
    string.
    If you want to allocate memory for a string, pass the number of
    non-null characters in it, plus one, to malloc, then copy the
    string into it, being sure to null-terminate the result.

    If you can be more specific about what you're trying to do,
    perhaps we can help with some details.
    --
    "I hope, some day, to learn to read.
    It seems to be even harder than writing."
    --Richard Heathfield

    Comment

    • Frederick Gotham

      #3
      Re: General method for dynamically allocating memory for a string

      smnoff posted:
      I have searched the internet for malloc and dynamic malloc; however, I
      still don't know or readily see what is general way to allocate memory
      to char * variable that I want to assign the substring that I found
      inside of a string.
      >
      Any ideas?

      Unchecked code, may contain an error or two:

      #include <stdlib.h>
      #include <stddef.h>
      #include <assert.h>

      char *to_release;

      void ReleaseLastStri ng(void)
      {
      free(to_release );
      }

      char const *CreateSubstrin g(char const *const p,
      size_t const istart,size_t const iend)
      {
      int assert_dummy = (assert(!!p),as sert(!!istart), assert(!!iend), 0);

      if(!p[iend+1]) return to_release = 0, p + istart;

      to_release = malloc(iend - istart + 1);

      memcpy(to_relea se,p,iend - istart);

      to_release[iend - istart] = 0;

      return to_release;
      }

      int main()
      {
      puts(CreateSubs tring("abcdefgh ijklmnop",2,7)) ;
      ReleaseLastStri ng();

      puts(CreateSubs tring("abcdefgh ijklmnop",4,15) );
      ReleaseLastStri ng();
      }

      --

      Frederick Gotham

      Comment

      • smnoff

        #4
        Re: General method for dynamically allocating memory for a string


        "Frederick Gotham" <fgothamNO@SPAM .comwrote in message
        news:r9qJg.1328 9$j7.326838@new s.indigo.ie...
        smnoff posted:
        >
        >I have searched the internet for malloc and dynamic malloc; however, I
        >still don't know or readily see what is general way to allocate memory
        >to char * variable that I want to assign the substring that I found
        >inside of a string.
        >>
        >Any ideas?
        >
        >
        Unchecked code, may contain an error or two:
        >
        #include <stdlib.h>
        #include <stddef.h>
        #include <assert.h>
        >
        char *to_release;
        >
        void ReleaseLastStri ng(void)
        {
        free(to_release );
        }
        >
        char const *CreateSubstrin g(char const *const p,
        size_t const istart,size_t const iend)
        {
        int assert_dummy = (assert(!!p),as sert(!!istart), assert(!!iend), 0);


        Why are there double exclamation marks in the line show above?






        Comment

        • Randall

          #5
          Re: General method for dynamically allocating memory for a string

          Frederick's code is hard to read and harder to learn from. Here is
          some fully checked code with lots of comments.


          ///////////////////////////////////////////////////////////////////////////////
          // file: substr.c
          // Note: C++ style comments are allowed for C99 compliant compilers.
          ///////////////////////////////////////////////////////////////////////////////
          #include <stdlib.h // for malloc() and free()
          #include <string.h // for strncpy()
          #include <sys/types.h // for size_t
          #include <stdio.h // for printf()

          char * substr( char * string, size_t start, size_t end);

          int main( void ) {

          char *str1 = substr("abcdefg hijklmnop",2,7) ;
          char *str2 = substr("abcdefg hijklmnop",4,15 );

          if( str1 != NULL ) {
          printf( "str1: %s\n", str1);
          } else {
          // Setting a null pointer to zero ensures you
          // can delete it more than once (free) without
          // undefined behavior. This is a good
          // programming habit.
          str1 = 0;
          }

          if( str2 != NULL ) {
          printf( "str2: %s\n", str2 );
          } else {
          // Setting a null pointer to zero ensures you
          // can delete it more than once (free) without
          // undefined behavior. This is a good
          // programming habit.
          str2 = 0;
          }

          free( str1 );
          free( str2 );

          return 0;
          }

          /**
          * Note: this function will return a newly allocated string. It
          * is your responsibility to delete this memory to prevent a leak.
          *
          * param "string" - the string you want to extract a substring from.
          * param "start" - the array index to begin your substring.

          * param "start" - the array index to begin your substring.
          * param "end" - the array index to terminate your substring.
          *
          * On Error: this function returns null;
          */
          char * substr( char * string, size_t start, size_t end) {
          // pointer to the substring on the heap
          char *subString;

          // calculate the total amount of memory needed
          // to hold the substring.
          // Algo: end - start + null terminator
          size_t subStringSize = end - start + 1;

          // request enough bytes to store the entire
          // substring and null terminator.
          subString = malloc( subStringSize );

          // test to make sure we got the memory
          // from malloc
          if( subString != NULL ) {
          // Note this copies one extra byte (the
          // null terminator's spot) which is garbage.
          // We have to terminate this string.
          strncpy( subString, string + start, subStringSize );

          subString[subStringSize] = '\0';
          }

          // This will either be NULL if we didn't get the
          // memory from malloc or it will have our substring.
          return subString;

          } // end function substr


          I hope this helps you.

          -Randall
          Frederick Gotham wrote:
          smnoff posted:
          >
          I have searched the internet for malloc and dynamic malloc; however, I
          still don't know or readily see what is general way to allocate memory
          to char * variable that I want to assign the substring that I found
          inside of a string.

          Any ideas?
          >
          >
          Unchecked code, may contain an error or two:
          >
          #include <stdlib.h>
          #include <stddef.h>
          #include <assert.h>
          >
          char *to_release;
          >
          void ReleaseLastStri ng(void)
          {
          free(to_release );
          }
          >
          char const *CreateSubstrin g(char const *const p,
          size_t const istart,size_t const iend)
          {
          int assert_dummy = (assert(!!p),as sert(!!istart), assert(!!iend), 0);
          >
          if(!p[iend+1]) return to_release = 0, p + istart;
          >
          to_release = malloc(iend - istart + 1);
          >
          memcpy(to_relea se,p,iend - istart);
          >
          to_release[iend - istart] = 0;
          >
          return to_release;
          }
          >
          int main()
          {
          puts(CreateSubs tring("abcdefgh ijklmnop",2,7)) ;
          ReleaseLastStri ng();
          >
          puts(CreateSubs tring("abcdefgh ijklmnop",4,15) );
          ReleaseLastStri ng();
          }
          >
          --
          >
          Frederick Gotham

          Comment

          • Keith Thompson

            #6
            Re: General method for dynamically allocating memory for a string

            "smnoff" <343rhinosourue us@hotmail.comw rites:
            "Frederick Gotham" <fgothamNO@SPAM .comwrote in message
            news:r9qJg.1328 9$j7.326838@new s.indigo.ie...
            >smnoff posted:
            >>
            >>I have searched the internet for malloc and dynamic malloc; however, I
            >>still don't know or readily see what is general way to allocate memory
            >>to char * variable that I want to assign the substring that I found
            >>inside of a string.
            >>>
            >>Any ideas?
            >>
            >>
            >Unchecked code, may contain an error or two:
            >>
            >#include <stdlib.h>
            >#include <stddef.h>
            >#include <assert.h>
            >>
            >char *to_release;
            >>
            >void ReleaseLastStri ng(void)
            >{
            > free(to_release );
            >}
            >>
            >char const *CreateSubstrin g(char const *const p,
            > size_t const istart,size_t const iend)
            >{
            > int assert_dummy = (assert(!!p),as sert(!!istart), assert(!!iend), 0);
            >
            Why are there double exclamation marks in the line show above?
            The assert() macro doesn't necessarily accept an argument of a type
            other than int. (It does in C99, but not all compilers support C99.)

            The ! (logical not) operator, applied to any scalar operand, yields
            the int value 1 if the operand compares equal to 0, 0 if it doesn't.
            A pointer value compares equal to 0 only if it's a null pointer. So
            !p means "p is a null pointer". Applying it a second time reverses
            the result, so !!p means "p is not a null pointer". !! normalizes a
            scalar value, mapping 0 to 0 and anything else to 1.

            So the declaration asserts that each of the pointers is non-null.

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

            • jaysome

              #7
              Re: General method for dynamically allocating memory for a string

              On 30 Aug 2006 21:04:57 -0700, "Randall" <randall.e.adam s@gmail.com>
              wrote:
              >Frederick's code is hard to read and harder to learn from. Here is
              >some fully checked code with lots of comments.
              >
              >
              >///////////////////////////////////////////////////////////////////////////////
              >// file: substr.c
              >// Note: C++ style comments are allowed for C99 compliant compilers.
              >///////////////////////////////////////////////////////////////////////////////
              >#include <stdlib.h // for malloc() and free()
              >#include <string.h // for strncpy()
              >#include <sys/types.h // for size_t
              >#include <stdio.h // for printf()
              >
              >char * substr( char * string, size_t start, size_t end);
              >
              >int main( void ) {
              >
              char *str1 = substr("abcdefg hijklmnop",2,7) ;
              char *str2 = substr("abcdefg hijklmnop",4,15 );
              >
              if( str1 != NULL ) {
              printf( "str1: %s\n", str1);
              } else {
              // Setting a null pointer to zero ensures you
              // can delete it more than once (free) without
              // undefined behavior. This is a good
              // programming habit.
              str1 = 0;
              }
              >
              if( str2 != NULL ) {
              printf( "str2: %s\n", str2 );
              } else {
              // Setting a null pointer to zero ensures you
              // can delete it more than once (free) without
              // undefined behavior. This is a good
              // programming habit.
              str2 = 0;
              }
              >
              free( str1 );
              free( str2 );
              >
              return 0;
              >}
              >
              >/**
              * Note: this function will return a newly allocated string. It
              * is your responsibility to delete this memory to prevent a leak.
              *
              * param "string" - the string you want to extract a substring from.
              * param "start" - the array index to begin your substring.
              >
              * param "start" - the array index to begin your substring.
              * param "end" - the array index to terminate your substring.
              *
              * On Error: this function returns null;
              */
              >char * substr( char * string, size_t start, size_t end) {
              // pointer to the substring on the heap
              char *subString;
              >
              // calculate the total amount of memory needed
              // to hold the substring.
              // Algo: end - start + null terminator
              size_t subStringSize = end - start + 1;
              >
              // request enough bytes to store the entire
              // substring and null terminator.
              subString = malloc( subStringSize );
              Make that:

              subString = malloc( subStringSize + 1 );
              >
              // test to make sure we got the memory
              // from malloc
              if( subString != NULL ) {
              // Note this copies one extra byte (the
              // null terminator's spot) which is garbage.
              // We have to terminate this string.
              strncpy( subString, string + start, subStringSize );
              >
              subString[subStringSize] = '\0';
              Otherwise this indexes one past the end of malloc()ed memory, which is
              undefined behavior.

              Best regards
              --
              jay

              Comment

              • Richard Heathfield

                #8
                Re: General method for dynamically allocating memory for a string

                Randall said:
                Frederick's code is hard to read and harder to learn from. Here is
                some fully checked code with lots of comments.
                It didn't compile for me, so I just took a very quick look, and one thing
                caught my eye:
                if( str1 != NULL ) {
                printf( "str1: %s\n", str1);
                } else {
                // Setting a null pointer to zero ensures you
                // can delete it more than once (free) without
                // undefined behavior. This is a good
                // programming habit.
                str1 = 0;
                }
                This is exactly equivalent to:

                if(str1 != NULL) {
                printf("str1: %s\n", str1);
                }

                The else is utterly unnecessary because, if str1 is not a null pointer, it
                is never entered, and if it /is/ a null pointer, setting it to a null
                pointer value is a redundant operation.
                if( str2 != NULL ) {
                printf( "str2: %s\n", str2 );
                } else {
                Likewise.

                --
                Richard Heathfield
                "Usenet is a strange place" - dmr 29/7/1999

                email: rjh at above domain (but drop the www, obviously)

                Comment

                • Frederick Gotham

                  #9
                  Re: General method for dynamically allocating memory for a string

                  Randall posted:
                  #include <stdlib.h // for malloc() and free()
                  #include <string.h // for strncpy()
                  #include <sys/types.h // for size_t


                  Non-standard header. "stddef.h" contains "size_t".


                  #include <stdio.h // for printf()
                  >
                  char * substr(char * string, size_t start, size_t end);


                  First parameter should be "pointer to const".


                  int main( void ) {
                  >
                  char *str1 = substr("abcdefg hijklmnop",2,7) ;
                  char *str2 = substr("abcdefg hijklmnop",4,15 );


                  Both variables should be const. (You don't want the address to change
                  before you pass it to "free".)


                  if( str1 != NULL ) {
                  printf( "str1: %s\n", str1);
                  } else {
                  // Setting a null pointer to zero ensures you
                  // can delete it more than once (free) without
                  // undefined behavior. This is a good
                  // programming habit.
                  str1 = 0;
                  }
                  >
                  if( str2 != NULL ) {
                  printf( "str2: %s\n", str2 );
                  } else {
                  // Setting a null pointer to zero ensures you
                  // can delete it more than once (free) without
                  // undefined behavior. This is a good
                  // programming habit.
                  str2 = 0;
                  }


                  As Richard Heathfield pointed out, both "else" clauses are redundant.


                  free( str1 );
                  free( str2 );
                  >
                  return 0;
                  }
                  >
                  /**
                  * Note: this function will return a newly allocated string. It
                  * is your responsibility to delete this memory to prevent a leak.
                  *
                  * param "string" - the string you want to extract a substring from.
                  * param "start" - the array index to begin your substring.
                  >
                  * param "start" - the array index to begin your substring.
                  * param "end" - the array index to terminate your substring.
                  *
                  * On Error: this function returns null;
                  */
                  char * substr( char * string, size_t start, size_t end) {


                  First parameter should be "pointer to const".


                  // pointer to the substring on the heap
                  char *subString;
                  >
                  // calculate the total amount of memory needed
                  // to hold the substring.
                  // Algo: end - start + null terminator
                  size_t subStringSize = end - start + 1;


                  Perhaps you should have written:

                  size_t len = end - start;

                  And then added the +1 only when malloc'ing.


                  // request enough bytes to store the entire
                  // substring and null terminator.
                  subString = malloc( subStringSize );


                  subString = malloc(len+1);


                  // test to make sure we got the memory
                  // from malloc
                  if( subString != NULL ) {
                  // Note this copies one extra byte (the
                  // null terminator's spot) which is garbage.
                  // We have to terminate this string.
                  strncpy( subString, string + start, subStringSize );


                  "memcpy" would be more efficient if you were strict about the length of
                  the string, e.g.:

                  assert( strlen(string) - istart >= len );


                  subString[subStringSize] = '\0';


                  Here you invoke undefine behaviour by writing past the end of the buffer.

                  subString[len] = 0;

                  You should _always_ check array indexes.


                  }
                  >
                  // This will either be NULL if we didn't get the
                  // memory from malloc or it will have our substring.
                  return subString;
                  >
                  } // end function substr
                  --

                  Frederick Gotham

                  Comment

                  • Richard Bos

                    #10
                    Re: General method for dynamically allocating memory for a string

                    Frederick Gotham <fgothamNO@SPAM .comwrote:
                    Randall posted:
                    >
                    #include <stdlib.h // for malloc() and free()
                    #include <string.h // for strncpy()
                    #include <sys/types.h // for size_t
                    >
                    Non-standard header. "stddef.h" contains "size_t".
                    So so <stdlib.h>, <string.h>, and...
                    #include <stdio.h // for printf()
                    .... <stdio.h>.

                    It is not often necessary to #include <stddef.h>. It is very rarely
                    necessary to do so just for the declaration of size_t. All headers whose
                    functions need it also declare it themselves, and it's a rare program
                    that does not use one of those headers.
                    char * substr(char * string, size_t start, size_t end);
                    >
                    First parameter should be "pointer to const".
                    No, it shouldn't, because that's not how the function is defined. It may
                    be a wise idea to _define_ it as a pointer to const char, or even a
                    const pointer to const char, and then also declare it as such, but
                    "should" is too strong.
                    if( str2 != NULL ) {
                    printf( "str2: %s\n", str2 );
                    } else {
                    // Setting a null pointer to zero ensures you
                    // can delete it more than once (free) without
                    // undefined behavior. This is a good
                    // programming habit.
                    str2 = 0;
                    }
                    >
                    As Richard Heathfield pointed out, both "else" clauses are redundant.
                    The reasoning given in the comment is also bogus. It is a very _bad_
                    programming habit to start expecting that you can free pointers twice.
                    // calculate the total amount of memory needed
                    // to hold the substring.
                    // Algo: end - start + null terminator
                    size_t subStringSize = end - start + 1;
                    >
                    Perhaps you should have written:
                    >
                    size_t len = end - start;
                    >
                    And then added the +1 only when malloc'ing.
                    Why?

                    Richard

                    Comment

                    • websnarf@gmail.com

                      #11
                      Re: General method for dynamically allocating memory for a string

                      smnoff wrote:
                      I have searched the internet for malloc and dynamic malloc; however, I still
                      don't know or readily see what is general way to allocate memory to char *
                      variable that I want to assign the substring that I found inside of a
                      string.
                      The C language makes this a bigger pain in the ass than it needs to be
                      as the discusion that has followed this shows. You can see how this is
                      done more easily in the Better String Library which you can get here:


                      If you just want to do it directly then:

                      #include <stdlib.h>
                      #include <string.h>

                      char * substralloc (const char * src, size_t pos, size_t len) {
                      size_t i;
                      char * substr;
                      if (NULL == src || len < pos) return NULL; /* Bad parameters */
                      for (len += pos, i = 0; i < len; i++) {
                      if ('\0' == src) {
                      if (i < pos) i = pos;
                      break;
                      }
                      }
                      i -= pos;
                      if (NULL != (substr = (char *) malloc ((1 + i) * sizeof (char)))) {
                      if (i) memcpy (substr, src+pos, i);
                      substr[i] = '\0';
                      }
                      return substr;
                      }

                      So if there is an error in the meaning of the parameters or if there is
                      a memory allocation failure then NULL is returned. If you ask for a
                      substring which is beyond the end of the source string, or whose length
                      exceeds the end othe source string, then the result is truncated.

                      --
                      Paul Hsieh
                      Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.



                      Comment

                      • Ben Pfaff

                        #12
                        Re: General method for dynamically allocating memory for a string

                        rlb@hoekstra-uitgeverij.nl (Richard Bos) writes:
                        Frederick Gotham <fgothamNO@SPAM .comwrote:
                        >
                        >Randall posted:
                        if( str2 != NULL ) {
                        printf( "str2: %s\n", str2 );
                        } else {
                        // Setting a null pointer to zero ensures you
                        // can delete it more than once (free) without
                        // undefined behavior. This is a good
                        // programming habit.
                        str2 = 0;
                        }
                        >>
                        > As Richard Heathfield pointed out, both "else" clauses are redundant.
                        >
                        The reasoning given in the comment is also bogus. It is a very _bad_
                        programming habit to start expecting that you can free pointers twice.
                        You can free a null pointer any number of times you like. I
                        think that is what the "it" in "delete it more than once" means.
                        --
                        "C has its problems, but a language designed from scratch would have some too,
                        and we know C's problems."
                        --Bjarne Stroustrup

                        Comment

                        • websnarf@gmail.com

                          #13
                          Re: General method for dynamically allocating memory for a string

                          Randall wrote:
                          Frederick's code is hard to read and harder to learn from. Here is
                          some fully checked code with lots of comments.
                          >
                          ///////////////////////////////////////////////////////////////////////////////
                          // file: substr.c
                          // Note: C++ style comments are allowed for C99 compliant compilers.
                          ///////////////////////////////////////////////////////////////////////////////
                          Note: C99 compliant compilers are in very short supply. (Though
                          compilers that *claim* to be C99 compilers is a little higher and those
                          that accept // comments are even higher.)
                          #include <stdlib.h // for malloc() and free()
                          #include <string.h // for strncpy()
                          #include <sys/types.h // for size_t
                          #include <stdio.h // for printf()
                          >
                          [...]
                          >
                          /**
                          * Note: this function will return a newly allocated string. It
                          * is your responsibility to delete this memory to prevent a leak.
                          *
                          * param "string" - the string you want to extract a substring from.
                          * param "start" - the array index to begin your substring.
                          >
                          * param "start" - the array index to begin your substring.
                          * param "end" - the array index to terminate your substring.
                          *
                          * On Error: this function returns null;
                          */
                          char * substr( char * string, size_t start, size_t end) {
                          // pointer to the substring on the heap
                          char *subString;
                          >
                          // calculate the total amount of memory needed
                          // to hold the substring.
                          // Algo: end - start + null terminator
                          size_t subStringSize = end - start + 1;
                          >
                          // request enough bytes to store the entire
                          // substring and null terminator.
                          subString = malloc( subStringSize );
                          >
                          // test to make sure we got the memory
                          // from malloc
                          if( subString != NULL ) {
                          // Note this copies one extra byte (the
                          // null terminator's spot) which is garbage.
                          // We have to terminate this string.
                          strncpy( subString, string + start, subStringSize );
                          This leads to UB, since you have not established that string + start is
                          a valid thing to be pointing at.

                          --
                          Paul Hsieh
                          Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.



                          Comment

                          • websnarf@gmail.com

                            #14
                            Re: General method for dynamically allocating memory for a string

                            Frederick Gotham wrote:
                            smnoff posted:
                            I have searched the internet for malloc and dynamic malloc; however, I
                            still don't know or readily see what is general way to allocate memory
                            to char * variable that I want to assign the substring that I found
                            inside of a string.

                            Any ideas?
                            >
                            Unchecked code, may contain an error or two:
                            (At least ...)
                            #include <stdlib.h>
                            #include <stddef.h>
                            #include <assert.h>
                            >
                            char *to_release;
                            Are you seriously making this global?
                            void ReleaseLastStri ng(void)
                            {
                            free(to_release );
                            }
                            >
                            char const *CreateSubstrin g(char const *const p,
                            size_t const istart,size_t const iend)
                            {
                            int assert_dummy = (assert(!!p),as sert(!!istart), assert(!!iend), 0);
                            >
                            if(!p[iend+1]) return to_release = 0, p + istart;
                            Homiesaywhat? What the hell is that if() condition trying to do? And
                            what is p+istart trying to do? Are you trying to say p += istart?
                            to_release = malloc(iend - istart + 1);
                            Ok, so what if istart iend? And what if to_release contained some
                            unfreed contents before this call -- wouldn't that lead to a leak?
                            memcpy(to_relea se,p,iend - istart);
                            What if to_release was set to NULL (because of a memory allocation
                            failure)?
                            to_release[iend - istart] = 0;
                            >
                            return to_release;
                            }
                            --
                            Paul Hsieh
                            Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.



                            Comment

                            • websnarf@gmail.com

                              #15
                              Re: General method for dynamically allocating memory for a string

                              websnarf@gmail. com wrote:
                              #include <stdlib.h>
                              #include <string.h>
                              >
                              char * substralloc (const char * src, size_t pos, size_t len) {
                              size_t i;
                              char * substr;
                              if (NULL == src || len < pos) return NULL; /* Bad parameters */
                              Whoops! That should just be if (NULL == src) return NULL;

                              --
                              Paul Hsieh
                              Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.



                              Comment

                              Working...