[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