destroying objects

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

    destroying objects

    This program simply reads a list of employes from the user, prints it
    and then destroys the allocated memory. I have a function
    free_memory(voi d *ptr) which will free the memory pointed to by
    pointer ptr. I included a pointer to this function in the emplist
    data structure free_employee_l ist. Is this a good way to program ??
    what if there are a number of such different data structures. Would it
    suffice to have a single free_memory function throughout the project
    and include a pointer to this function in every data structure ??

    #include <stdio.h>
    #include <stdlib.h>

    typedef struct _employee
    {
    int eid;
    float sal;
    int age;
    }employee;

    typedef struct _emplist
    {
    int n;
    employee *e;
    void (*free_employee _list)();
    }emplist;


    void free_memory(voi d *ptr)
    {
    free(ptr);
    printf("\nMemor y freed\n");
    }
    int main(void)
    {
    emplist *list;
    int i;

    list = malloc(sizeof(* list));
    if(list == NULL)
    {
    fprintf(stderr, "memory allocation failed\n");
    return 1;
    }

    list->free_employee_ list = free_memory;
    printf("Enter number of employees\n");
    scanf("%d", &list->n);

    list->e = malloc(sizeof(e mployee) * list->n);

    if(list->e == NULL)
    {
    fprintf(stderr, "memory allocation failed\n");
    return 1;
    }

    for(i = 0; i < list->n; i++)
    {
    printf("Enter id, age, salary\n");
    scanf("%d %d %f", &list->e[i].eid, &list->e[i].age, &list-
    >e[i].sal);
    }

    for(i = 0; i < list->n; i++)
    {
    printf("Employe id: %d age: %d sal: %f\n", list->e[i].eid, list-
    >e[i].age, list->e[i].sal);
    }

    list->free_employee_ list(list);

    return 0;
    }
  • Malcolm McLean

    #2
    Re: destroying objects


    "pereges" <Broli00@gmail. comwrote in message news:
    This program simply reads a list of employes from the user, prints it
    and then destroys the allocated memory. I have a function
    free_memory(voi d *ptr) which will free the memory pointed to by
    pointer ptr. I included a pointer to this function in the emplist
    data structure free_employee_l ist. Is this a good way to program ??
    >
    It's (arguably) a good way to program, but not in C. C's syntax isn't rich
    enough to support a heavily indirected set of function pointers embedded in
    their own structures. It's an easy route to unreadability.

    However the same idea in C++ is fine. The language will call destructors
    automatically for you.

    --
    Free games and programming goodies.


    Comment

    • pete

      #3
      Re: destroying objects

      pereges wrote:
      This program simply reads a list of employes from the user, prints it
      and then destroys the allocated memory. I have a function
      free_memory(voi d *ptr) which will free the memory pointed to by
      pointer ptr. I included a pointer to this function in the emplist
      data structure free_employee_l ist. Is this a good way to program ??
      what if there are a number of such different data structures. Would it
      suffice to have a single free_memory function throughout the project
      and include a pointer to this function in every data structure ??
      >
      #include <stdio.h>
      #include <stdlib.h>
      >
      typedef struct _employee
      {
      int eid;
      float sal;
      int age;
      }employee;
      >
      typedef struct _emplist
      {
      int n;
      employee *e;
      void (*free_employee _list)();
      }emplist;
      >
      >
      void free_memory(voi d *ptr)
      {
      free(ptr);
      printf("\nMemor y freed\n");
      }
      int main(void)
      {
      emplist *list;
      int i;
      >
      list = malloc(sizeof(* list));
      if(list == NULL)
      {
      fprintf(stderr, "memory allocation failed\n");
      return 1;
      }
      >
      list->free_employee_ list = free_memory;
      printf("Enter number of employees\n");
      scanf("%d", &list->n);
      >
      list->e = malloc(sizeof(e mployee) * list->n);
      >
      if(list->e == NULL)
      {
      fprintf(stderr, "memory allocation failed\n");
      return 1;
      }
      >
      for(i = 0; i < list->n; i++)
      {
      printf("Enter id, age, salary\n");
      scanf("%d %d %f", &list->e[i].eid, &list->e[i].age, &list-
      >e[i].sal);
      }
      >
      for(i = 0; i < list->n; i++)
      {
      printf("Employe id: %d age: %d sal: %f\n", list->e[i].eid, list-
      >e[i].age, list->e[i].sal);
      }
      >
      list->free_employee_ list(list);
      >
      return 0;
      }
      It looks overly complicated to me.
      I don't understand why it isn't just as simple
      as allocating an array of structures and then freeing it.

      /* BEGIN employees_2.c */

      #include <stdio.h>
      #include <stdlib.h>

      int main(void)
      {
      struct {
      int eid;
      double sal;
      int age;
      } *e_ptr;
      unsigned i, n;

      puts("/* BEGIN employees_2.c output */\n");
      puts("Enter number of employees");
      if (scanf("%u", &n) != 1) {
      puts("Forget about it.");
      exit(EXIT_SUCCE SS);
      }
      e_ptr = malloc(n * sizeof *e_ptr);
      if (e_ptr == NULL) {
      puts("e_ptr == NULL");
      exit(EXIT_FAILU RE);
      }

      for (i = 0; i != n; ++i) {
      puts("Enter id, age, salary");
      if (scanf("%d %d %lf",
      &e_ptr[i].eid,
      &e_ptr[i].age,
      &e_ptr[i].sal) != 3)
      {
      puts("Forget about it.");
      break;
      }
      }
      putchar('\n');
      for (n = 0; i != n; ++n) {
      printf("Employe id: %d age: %d sal: %f\n",
      e_ptr[n].eid,
      e_ptr[n].age,
      e_ptr[n].sal);
      }
      free(e_ptr);
      puts("\nArray is freed.\n");
      puts("/* END employees_2.c output */");
      return 0;
      }

      /* END employees_2.c */


      --
      pete

      Comment

      • Barry Schwarz

        #4
        Re: destroying objects

        On Wed, 11 Jun 2008 11:11:24 -0700 (PDT), pereges <Broli00@gmail. com>
        wrote:
        >This program simply reads a list of employes from the user, prints it
        >and then destroys the allocated memory. I have a function
        >free_memory(vo id *ptr) which will free the memory pointed to by
        >pointer ptr. I included a pointer to this function in the emplist
        >data structure free_employee_l ist. Is this a good way to program ??
        Is it a good idea to have a function whose only purpose is to call a
        standard function? I think not.

        Is it a good idea to have a function pointer point to this function?
        Not unless you have more than one such function and the point where
        you decide which one to use is removed from the point where you call
        the function.

        Is it a good idea to have this pointer as a member of the struct
        _emplist? Probably, since everything else you need to "control"
        struct _employee is included in struct _emplist.
        >what if there are a number of such different data structures. Would it
        >suffice to have a single free_memory function throughout the project
        >and include a pointer to this function in every data structure ??
        If you only have one function, why bother wasting the space for a
        pointer to it in every data structure.
        >
        >#include <stdio.h>
        >#include <stdlib.h>
        >
        >typedef struct _employee
        >{
        int eid;
        float sal;
        int age;
        >}employee;
        >
        >typedef struct _emplist
        >{
        int n;
        employee *e;
        void (*free_employee _list)();
        >}emplist;
        >
        >
        >void free_memory(voi d *ptr)
        >{
        free(ptr);
        printf("\nMemor y freed\n");
        It would be nice if you said what memory was being freed. Something
        like
        printf("\nMemor y allocated at %p freed\n", ptr);
        free(ptr);
        >}
        >int main(void)
        >{
        emplist *list;
        int i;
        >
        list = malloc(sizeof(* list));
        if(list == NULL)
        {
        fprintf(stderr, "memory allocation failed\n");
        It would be nice to indicate which allocation failed.
        return 1;
        To be portable use EXIT_FAILURE.
        }
        >
        list->free_employee_ list = free_memory;
        printf("Enter number of employees\n");
        scanf("%d", &list->n);
        >
        list->e = malloc(sizeof(e mployee) * list->n);
        >
        if(list->e == NULL)
        {
        fprintf(stderr, "memory allocation failed\n");
        You ought to free list at this point.
        return 1;
        }
        >
        for(i = 0; i < list->n; i++)
        {
        printf("Enter id, age, salary\n");
        scanf("%d %d %f", &list->e[i].eid, &list->e[i].age, &list-
        >>e[i].sal);
        }
        >
        for(i = 0; i < list->n; i++)
        {
        printf("Employe id: %d age: %d sal: %f\n", list->e[i].eid, list-
        >>e[i].age, list->e[i].sal);
        }
        >
        list->free_employee_ list(list);
        By not freeing list->e before freeing list, you have created a memory
        leak.
        >
        return 0;
        >}

        Remove del for email

        Comment

        • Nick Keighley

          #5
          Re: destroying objects

          On 11 Jun, 19:11, pereges <Brol...@gmail. comwrote:

          I agree with the other posters

          <snip>
          typedef struct _employee
          identifiers beginning with _ are in the reserved namespace.
          That is only compiler writters and standard library implementors
          should use it. (The rules are slightly more complicated but
          "don't begin identifiers with underscore" is easy to remember).

          <snip>
            printf("Enter number of employees\n");
            scanf("%d", &list->n);
          >
            list->e = malloc(sizeof(e mployee) * list->n);
          failure to test return value of scanf(). scanf() is tricky to use,
          its error recovery is poor (try entering a string of letters).
          Use fgets() and fscanf().

          <snip>


          --
          Nick Keighley

          The fscanf equivalent of fgets is so simple
          that it can be used inline whenever needed:-
          char s[NN + 1] = "", c;
          int rc = fscanf(fp, "%NN[^\n]%1[\n]", s, &c);
          if (rc == 1) fscanf("%*[^\n]%*c);
          if (rc == 0) getc(fp);

          (actually it can't be *that* simple as I've just spotted two syntax
          errors...)

          Comment

          • Chris Thomasson

            #6
            Re: destroying objects

            "Nick Keighley" <nick_keighley_ nospam@hotmail. comwrote in message
            news:3cee76d5-98b3-4978-8992-f21c281c2428@x4 1g2000hsb.googl egroups.com...
            On 11 Jun, 19:11, pereges <Brol...@gmail. comwrote:
            I agree with the other posters
            <snip>
            typedef struct _employee
            identifiers beginning with _ are in the reserved namespace.
            That is only compiler writters and standard library implementors
            should use it. (The rules are slightly more complicated but
            "don't begin identifiers with underscore" is easy to remember).
            Something like the following is perfectly fine:
            _______________ _______________ _______________ ____
            #include <stdio.h>

            void foo(int _this) {
            printf("%d\n", _this);
            }

            int main(void) {
            foo(1);
            getchar();
            return 0;
            }

            _______________ _______________ _______________ ____






            [...]

            Comment

            • CBFalconer

              #7
              Re: destroying objects

              Chris Thomasson wrote:
              "Nick Keighley" <nick_keighley_ nospam@hotmail. comwrote:
              >pereges <Brol...@gmail. comwrote:
              >
              .... snip ...
              >>
              >>typedef struct _employee
              >>
              >identifiers beginning with _ are in the reserved namespace.
              >That is only compiler writters and standard library implementors
              >should use it. (The rules are slightly more complicated but
              >"don't begin identifiers with underscore" is easy to remember).
              >
              Something like the following is perfectly fine:
              >
              #include <stdio.h>
              >
              void foo(int _this) {
              printf("%d\n", _this);
              }
              >
              int main(void) {
              foo(1);
              getchar();
              return 0;
              }
              Not if stdio.h has (legitimately) defined a macro for _this. Using
              plain this is safer, since the scope of this only extends to the
              function closing '}'.

              --
              [mail]: Chuck F (cbfalconer at maineline dot net)
              [page]: <http://cbfalconer.home .att.net>
              Try the download section.


              ** Posted from http://www.teranews.com **

              Comment

              • Chris Thomasson

                #8
                Re: destroying objects

                "CBFalconer " <cbfalconer@yah oo.comwrote in message
                news:4851A39C.8 9D36C85@yahoo.c om...
                Chris Thomasson wrote:
                >"Nick Keighley" <nick_keighley_ nospam@hotmail. comwrote:
                >>pereges <Brol...@gmail. comwrote:
                >>
                ... snip ...
                >>>
                >>>typedef struct _employee
                >>>
                >>identifiers beginning with _ are in the reserved namespace.
                >>That is only compiler writters and standard library implementors
                >>should use it. (The rules are slightly more complicated but
                >>"don't begin identifiers with underscore" is easy to remember).
                >>
                >Something like the following is perfectly fine:
                >>
                >#include <stdio.h>
                >>
                >void foo(int _this) {
                > printf("%d\n", _this);
                >}
                >>
                >int main(void) {
                > foo(1);
                > getchar();
                > return 0;
                >}
                >
                Not if stdio.h has (legitimately) defined a macro for _this. Using
                plain this is safer, since the scope of this only extends to the
                function closing '}'.
                Ouch. Well, I thought that identifiers which start with a double underscore,
                single underscore followed by a uppercase character, or a single underscore
                at file scope are not allowed. Since function parameters are not at file
                scope, well, using `_this' should be fine. Where am I going wrong?

                Thanks.

                Comment

                • Chris Thomasson

                  #9
                  Re: destroying objects

                  "CBFalconer " <cbfalconer@yah oo.comwrote in message
                  news:4851A39C.8 9D36C85@yahoo.c om...
                  Chris Thomasson wrote:
                  >"Nick Keighley" <nick_keighley_ nospam@hotmail. comwrote:
                  >>pereges <Brol...@gmail. comwrote:
                  >>
                  ... snip ...
                  >>>
                  >>>typedef struct _employee
                  >>>
                  >>identifiers beginning with _ are in the reserved namespace.
                  >>That is only compiler writters and standard library implementors
                  >>should use it. (The rules are slightly more complicated but
                  >>"don't begin identifiers with underscore" is easy to remember).
                  >>
                  >Something like the following is perfectly fine:
                  >>
                  >#include <stdio.h>
                  >>
                  >void foo(int _this) {
                  > printf("%d\n", _this);
                  >}
                  >>
                  >int main(void) {
                  > foo(1);
                  > getchar();
                  > return 0;
                  >}
                  >
                  Not if stdio.h has (legitimately) defined a macro for _this. Using
                  plain this is safer, since the scope of this only extends to the
                  function closing '}'.
                  I agree that using `this' would be a heck of a lot safer. Its been a nasty
                  habit of mine to use `_this'.

                  ;^(...

                  Comment

                  • Keith Thompson

                    #10
                    Re: destroying objects

                    CBFalconer <cbfalconer@yah oo.comwrites:
                    Chris Thomasson wrote:
                    >"Nick Keighley" <nick_keighley_ nospam@hotmail. comwrote:
                    >>pereges <Brol...@gmail. comwrote:
                    >>
                    ... snip ...
                    >>>
                    >>>typedef struct _employee
                    >>>
                    >>identifiers beginning with _ are in the reserved namespace.
                    >>That is only compiler writters and standard library implementors
                    >>should use it. (The rules are slightly more complicated but
                    >>"don't begin identifiers with underscore" is easy to remember).
                    >>
                    >Something like the following is perfectly fine:
                    >>
                    >#include <stdio.h>
                    >>
                    >void foo(int _this) {
                    > printf("%d\n", _this);
                    >}
                    >>
                    >int main(void) {
                    > foo(1);
                    > getchar();
                    > return 0;
                    >}
                    >
                    Not if stdio.h has (legitimately) defined a macro for _this. Using
                    plain this is safer, since the scope of this only extends to the
                    function closing '}'.
                    stdio.h cannot legally define a macro named "_this". As Nick wrote
                    above, the rules are "slightly more complicated". Specifically (C99
                    7.1.3):

                    Identifiers beginning with an underscore and an uppercase letter,
                    or with two underscores, are always reserved for any use. For
                    example, stdio.h could define a macro "__this" or "_This".

                    Identifiers beginning with an underscore are reserved for use as
                    identifiers with file scope. For example, stdio.h could declare a
                    function "_this".

                    But since "_this" in Chris's code is not at file scope, it doesn't
                    violate one of the standard's reservations.

                    The above program is perfectly legal, and in fact it's arguably
                    strictly conforming (ignoring the possibility of printf failing).

                    However, I wouldn't call it "perfectly fine" on stylistic grounds.
                    First, I prefer to avoid declaring identifiers starting with
                    underscores altogether, since it's easier than keeping track of the
                    distinction between the two cases I cited above (and expecting anyone
                    reading the code to do so as well). It's not as if avoiding leading
                    underscores places a burdensome limitation on the set of identifiers I
                    can use.

                    Second, the ``getchar()'' call is superfluous; all it does is silently
                    wait for user input before terminating the program, which is just
                    annoying. (Yes, there are systems where this is useful, but there are
                    other ways to achieve the same effect.)

                    --
                    Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
                    Nokia
                    "We must do something. This is something. Therefore, we must do this."
                    -- Antony Jay and Jonathan Lynn, "Yes Minister"

                    Comment

                    • CBFalconer

                      #11
                      Re: destroying objects

                      Chris Thomasson wrote:
                      "CBFalconer " <cbfalconer@yah oo.comwrote in message
                      >Chris Thomasson wrote:
                      >>
                      .... snip ...
                      >>
                      >>Something like the following is perfectly fine:
                      >>>
                      >>#include <stdio.h>
                      >>>
                      >>void foo(int _this) {
                      >> printf("%d\n", _this);
                      >>}
                      >>>
                      >>int main(void) {
                      >> foo(1);
                      >> getchar();
                      >> return 0;
                      >>}
                      >>
                      >Not if stdio.h has (legitimately) defined a macro for _this. Using
                      >plain this is safer, since the scope of this only extends to the
                      >function closing '}'.
                      >
                      Ouch. Well, I thought that identifiers which start with a double
                      underscore, single underscore followed by a uppercase character, or
                      a single underscore at file scope are not allowed. Since function
                      parameters are not at file scope, well, using `_this' should be
                      fine. Where am I going wrong?
                      When macros are expanded the system has not parsed the function
                      header. It is just so much more text to be treated according to
                      the macro rules.

                      --
                      [mail]: Chuck F (cbfalconer at maineline dot net)
                      [page]: <http://cbfalconer.home .att.net>
                      Try the download section.


                      ** Posted from http://www.teranews.com **

                      Comment

                      • Keith Thompson

                        #12
                        Re: destroying objects

                        CBFalconer <cbfalconer@yah oo.comwrites:
                        Chris Thomasson wrote:
                        >"CBFalconer " <cbfalconer@yah oo.comwrote in message
                        >>Chris Thomasson wrote:
                        >>>
                        ... snip ...
                        >>>
                        >>>Something like the following is perfectly fine:
                        >>>>
                        >>>#include <stdio.h>
                        >>>>
                        >>>void foo(int _this) {
                        >>> printf("%d\n", _this);
                        >>>}
                        >>>>
                        >>>int main(void) {
                        >>> foo(1);
                        >>> getchar();
                        >>> return 0;
                        >>>}
                        >>>
                        >>Not if stdio.h has (legitimately) defined a macro for _this. Using
                        >>plain this is safer, since the scope of this only extends to the
                        >>function closing '}'.
                        >>
                        >Ouch. Well, I thought that identifiers which start with a double
                        >underscore, single underscore followed by a uppercase character, or
                        >a single underscore at file scope are not allowed. Since function
                        >parameters are not at file scope, well, using `_this' should be
                        >fine. Where am I going wrong?
                        >
                        When macros are expanded the system has not parsed the function
                        header. It is just so much more text to be treated according to
                        the macro rules.
                        But that's not an issue in this case, since <stdio.hcanno t legally
                        define _this as a macro. See my other response.

                        --
                        Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
                        Nokia
                        "We must do something. This is something. Therefore, we must do this."
                        -- Antony Jay and Jonathan Lynn, "Yes Minister"

                        Comment

                        • Harald van =?UTF-8?b?RMSzaw==?=

                          #13
                          Re: destroying objects

                          On Thu, 12 Jun 2008 18:02:11 -0700, Keith Thompson wrote:
                          CBFalconer <cbfalconer@yah oo.comwrites:
                          >Chris Thomasson wrote:
                          >>Something like the following is perfectly fine:
                          >>>
                          >>#include <stdio.h>
                          >>>
                          >>void foo(int _this) {
                          >> printf("%d\n", _this);
                          >>}
                          >>[...]
                          >Not if stdio.h has (legitimately) defined a macro for _this. Using
                          >plain this is safer, since the scope of this only extends to the
                          >function closing '}'.
                          >
                          stdio.h cannot legally define a macro named "_this". [snip explanation]
                          Yes, it can: _this is reserved for use by the implementation at file
                          scope. This means an implementation is allowed to provide a declaration of
                          a function named _this in <stdio.h>. And 7.1.4 states that "Any function
                          declared in a header may be additionally implemented as a function-like
                          macro defined in the header," which does not only apply to the functions
                          described by the standard. Existing implementations make use of this
                          permission with macro definitions of _toupper and _tolower in <ctype.h>.

                          That said, <stdio.hcanno t legally define an object-like macro named
                          "_this", so the code by Chris Thomasson is still perfectly fine.

                          Comment

                          • Keith Thompson

                            #14
                            Re: destroying objects

                            Harald van Dijk <truedfx@gmail. comwrites:
                            On Thu, 12 Jun 2008 18:02:11 -0700, Keith Thompson wrote:
                            >CBFalconer <cbfalconer@yah oo.comwrites:
                            >>Chris Thomasson wrote:
                            >>>Something like the following is perfectly fine:
                            >>>>
                            >>>#include <stdio.h>
                            >>>>
                            >>>void foo(int _this) {
                            >>> printf("%d\n", _this);
                            >>>}
                            >>>[...]
                            >>Not if stdio.h has (legitimately) defined a macro for _this. Using
                            >>plain this is safer, since the scope of this only extends to the
                            >>function closing '}'.
                            >>
                            >stdio.h cannot legally define a macro named "_this". [snip explanation]
                            >
                            Yes, it can: _this is reserved for use by the implementation at file
                            scope. This means an implementation is allowed to provide a declaration of
                            a function named _this in <stdio.h>. And 7.1.4 states that "Any function
                            declared in a header may be additionally implemented as a function-like
                            macro defined in the header," which does not only apply to the functions
                            described by the standard. Existing implementations make use of this
                            permission with macro definitions of _toupper and _tolower in <ctype.h>.
                            Interesting. (I overlooked function-like macros.) I think you're
                            right, but I wonder if that was the intent. Perhaps the committee
                            just didn't think about macros for non-standard functions in standard
                            headers.

                            It would have been just as easy for implementations to use __toupper
                            and __tolower.
                            That said, <stdio.hcanno t legally define an object-like macro named
                            "_this", so the code by Chris Thomasson is still perfectly fine.
                            Right.

                            --
                            Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
                            Nokia
                            "We must do something. This is something. Therefore, we must do this."
                            -- Antony Jay and Jonathan Lynn, "Yes Minister"

                            Comment

                            • Harald van =?UTF-8?b?RMSzaw==?=

                              #15
                              Re: destroying objects

                              On Fri, 13 Jun 2008 09:49:28 -0700, Keith Thompson wrote:
                              Harald van Dijk <truedfx@gmail. comwrites:
                              >Existing implementations
                              >make use of this permission with macro definitions of _toupper and
                              >_tolower in <ctype.h>.
                              >
                              It would have been just as easy for implementations to use __toupper and
                              __tolower.
                              Normally, this would be true, but _toupper and _tolower predate the
                              original C standard by several years. According to the Single UNIX
                              Specification, they are derived from Issue 1 of the SVID, which is from
                              1985. It would have been easier for the C standard to define these
                              functions than for implementations to rename them.

                              Comment

                              Working...