2

On trying to understand the functionality of container_of() from the source code linux kernel Definition of container_of, I found out that the below line in the definition of the macro looks like doing nothing.

const typeof( ((type *)0)->member ) *__mptr = (ptr); \

So, I wrote a simple C program without the said line and tried to the compare the obtained results. Basically, I am trying to Understand how is the new implementation my_contianer_of() different from container_of() ? when both the implementation give same results.

#include <stdio.h>
#include <stddef.h>

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

#define my_container_of(ptr, type, member) ({ \
        (char *)ptr - offsetof(type, member);})

struct container {
    int *i;
    char c;
    float f;
};

void foo(char *cptr)
{
    printf("foo  : %p\n", my_container_of(cptr, struct container, c));
}

int main(int argc, char *argv[])
{
    struct container tc;

    printf("&tc  : %p\n", &tc);
    printf("cof  : %p\n", container_of(&tc.c, struct container, c));
    printf("mycof: %p\n", my_container_of(&tc.c, struct container, c));

    foo(&tc.c);

    return 0;
}

The below is the sample output for the above c program.

&tc  : 0x7ffca543e0c0
cof  : 0x7ffca543e0c0
mycof: 0x7ffca543e0c0
foo  : 0x7ffca543e0c0

Please don't mark this question as the duplicate of any other question or this Understanding container_of macro in the linux kernel as those questions did not provide the required answer for my query.

1
  • There could be edge cases that the simplified version does not handle. Or it's just a matter of eliminating compiler implicit typecasting warnings. Commented Sep 6, 2018 at 6:08

1 Answer 1

3

Your implementation isn't type safe. It doesn't make sure that the pointer you pass is to the same type as the member, which could lead to bugs. So, for instance:

my_container_of(&tc.f, struct container, c)

Will compile just fine. The kernel version will at least issue a warning about incompatible pointer types. Or flat out cause compilation to halt, depending on your GCC flags.

Naturally, the kernel version doesn't prevent all bugs (if f and c were of the same type, for instance). But this is one it can catch, and should.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.