Search code examples
cstructmallocpaddingfree

Is it vali to call free with a pointer to the first member?


Is it okay to call free on a pointer which is pointing at the first member of a struct (and the struct is the one involved with malloc)? I know in principle the pointer is pointing at the right thing anyway...

struct s {int x;};
//in main
struct s* test;
test = (struct s*) malloc(sizeof(*test));
int* test2;
test2 = &(test->x);
free(test2); //is this okay??

Also, will the answer change if int x is replaced with a struct?

Update: Why would I want to write code like this?

struct s {int x;};
struct sx1 {struct s test; int y;}; //extending struct s
struct sx2 {struct s test; int z;}; //another
// ** some functions to keep track of the number of references to each variable of type struct s 
int release(struct s* ptr){
  //if the number of references to *ptr is 0 call free on ptr
}
int main(){
    struct sx1* test1;
    struct sx2* test2;
    test1 = (sx1*) malloc(sizeof(*sx1));
    test2 = (sx2*) malloc(sizeof(*sx2));
    //code that changes the number of references to test1 and test2, calling functions defined in **
    release(test1);
    release(test2);
}

Solution

  • Yes this is ok.

    6.7.2.1

    1. Within a structure object, the non-bit-field members and the units in which bit-fields reside have addresses that increase in the order in which they are declared. A pointer to a structure object, suitably converted, points to its initial member (or if that member is a bit-field, then to the unit in which it resides), and vice versa. There may be unnamed padding within a structure object, but not at its beginning.

    Which means that this is defined:

    struct s {int x;};
    struct s* test;
    test = (struct s*) malloc(sizeof(*test));
    int* p = &(test->x);
    free(p);