I have created the following code to understand offsetof() and container_of() macros. Here the printf() show two different address instead of same address. What am I doing wrong?
#include <stdio.h>
#include <stddef.h>
typedef unsigned char Byte;
#define container(ptr, type, member) \
({ \
(type *)((Byte *)ptr - offsetof(type, member)); \
})
typedef struct
{
size_t size;
void *block;
}Header;
int main()
{
void *ptr = malloc(3);
Header *pHdr = container(ptr, Header, block);
printf("%p %p\n", ptr, pHdr->block);
return 0;
}
It looks like the code is attempting to inspect/demonstrate the inner workings of a malloc implementation. Your container
macro is working, the problem is that your Header
structure definition is incorrect:
typedef struct
{
size_t size;
void* block;
} Header;
This is implying that malloc
keeps the size of the allocation in memory followed by a pointer to the block. This is not accurate - you are assuming an extra level of indirection that does not exist. Your code ends up interpreting the contents of the data block as a void*
. Since you haven't initialized that memory, you see whatever happens to be there (from the values you gave, it looks like you may be seeing the pointer to the next free block - when you malloc(0)
you're not allowed to write to the data block so the implementation may use it - see struct malloc_chunk
in the glibc malloc implementation for example).
A more correct structure definition (works for me on both clang-503.0.40/LLVM 5.1 and VC 2012) would be:
typedef struct
{
size_t size;
char block[0];
} Header;
You will also need to change your printf
to print the address of block
:
printf("%p %p\n", ptr, &pHdr->block);
Do note, of course, that there is no guarantee that every malloc
implementation will actually store the block size immediately before the block, so this may not always work.