[gPXE] ptr_to_struct->member != ptr_to_struct + offsetof(struct, member)

sobtwmxt sobtwmxt at sdf.lonestar.org
Thu Nov 26 19:39:08 EST 2009


  I am sending a reply to a question I post earlier.  Actually, my
earlier post had 2 sections.  This meessage relates to the 1st section 
of the original post.  I am relying to myself on a public list for 2
reasons:

  1. My original post was not clear.  I confused the simplified,
     straight to the point code, with the real code.
  2. I think that other people were, are, and will be intrested on
     the topic, here as well as on related projects.  Searching 
     google for __mptr shows that I might be right.  I find the list
     archive a good place for sharing this knowledge.
      

On Thu, Nov 26, 2009 at 01:20:04AM +0000, sobtwmxt wrote:
> 1. Why the following asserion fail?  How to correct it?
> 
>         struct person {
>                 struct refcnt refcnt;
>                 const char *givenName;
>                 const char *fatherName;
>         };
> 
>         fatherName = zalloc( 10 );
> 
>         static void person_free_fatherName ( struct refcnt *refcnt ) {
>                 struct person *person =
>                         container_of ( refcnt, struct person, refcnt );
> 
>                 assert ( (void *) person->fatherName ==
>                             (void *) uri +
>                                 offsetof(struct person, fatherName) );
>                 free ( uri + offsetof(struct uri, decoded_user) );
>         };
> 
> 


  The fix is:

--- code.orig	2009-11-26 12:28:39.000000000 +0100
+++ code.new	2009-11-26 12:27:02.000000000 +0100
@@ -2,17 +2,20 @@
         struct refcnt refcnt;
         const char *givenName;
         const char *fatherName;
-};
+} person;
+
+strcut person *p = &person;
 
-fatherName = zalloc( 10 );
+p->fatherName = zalloc( 10 );
 
 static void person_free_fatherName ( struct refcnt *refcnt ) {
         struct person *person =
                 container_of ( refcnt, struct person, refcnt );
 
         assert ( (void *) &person->fatherName ==
-                            (void *) uri +
+                            (void *) person +
                                 offsetof(struct person, fatherName) );
-        free ( uri + offsetof(struct uri, decoded_user) );
+        free ( * (char **) ( (void *) person + 
+                        offsetof(struct person, fatherName) ) );
 };
 

=======================================================================


  The following example might help clarifying things:

Script started on Thu Nov 26 12:12:30 2009
$ cat example.c
#include <assert.h>
#include <stdlib.h>

#undef offsetof
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

#undef container_of
#define container_of(ptr, type, member) ({                      \
        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
        (type *)( (char *)__mptr - offsetof(type, member) );})


static struct person {
        const int  id;
        const char *givenName;
        const char *fatherName;
} person;


int main ( void ) {
        struct person *p1 = &person;

        p1->fatherName = malloc( 10 );
        struct person *p2 =
               container_of ( &p1->id, struct person, id );
        assert ( p1 == p2 );
        assert ( (void *) &p1->fatherName ==
                    (void *) p1 + offsetof(struct person, fatherName) );
        assert ( (char **) &p1->fatherName == (char **) 
                 ( (void *) p1 + offsetof(struct person, fatherName) ) );
        /* freeing p1->fatherName at this point, by calling
         * free ( * (char **) 
                      ( (void *) p1 + 
                               offsetof(struct person, fatherName) ) )
         * will not confuse the dynamic memory allocator.
         */ 
        return EXIT_SUCCESS;
}
$ cc -Wall example.c -o example
$ ./example
$ # No failure of assertions when ./example ran.
$ exit
exit

Script done on Thu Nov 26 12:12:55 2009

-- 
sobtwmxt at sdf.lonestar.org
SDF Public Access UNIX System - http://sdf.lonestar.org


More information about the gPXE mailing list