John
John

Reputation: 697

Find holes in C structs due to alignment

Is there a way in gcc or clang (or any other compiler) to spit information about whether a struct has holes (memory alignment - wise) in it ?

Thank you.

ps: If there is another way to do it, please do inform me.

Upvotes: 13

Views: 5628

Answers (7)

yoonghm
yoonghm

Reputation: 4655

You need a parser which understands c/c++ structures and includes necessary includes files.

As replied by @roee-gavirel, I think the easier solution is to create a test program to print out the offsets

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

typedef struct tData {
  long   id;       /* 8 bytes */
  char   name[8];  /* 8 bytes */
  float  salary;   /* 4 bytes */
} tData;

tData d;

int main()
{
  size_t s_tData  = sizeof(tData);
  size_t s_id     = sizeof(d.id);
  size_t s_name   = sizeof(d.name);
  size_t s_salary = sizeof(d.salary);

  printf("sizeof(tData) = %zu\n\n", sizeof(d));

  printf("'id'     is at = %3zu  occupies %zu bytes\n",
         offsetof(tData, id), s_id);
  printf("'name'   is at = %3zu  occupies %zu bytes\n",
         offsetof(tData, name), s_name);
  printf("'salary' is at = %3zu  occupies %zu bytes\n",
         offsetof(tData, salary), s_salary);

  printf("\n");

  if (s_tData != s_id + s_name + s_salary)
    printf("There is/are holes\n");

  return 0;
}

Upvotes: 0

Jens
Jens

Reputation: 72756

Gimpel's FlexeLint/PClint can do this.

$ cat tst.c
int main (void)
{
    struct {
        char c;
        double d;
        short s;
    } f = { 1, 2.0, 3 };

    return f.c;
}

It will report

$ flexelint -w1 +e95? tst.c
FlexeLint for C/C++ (Unix) Vers. 9.00L, Copyright Gimpel Software 1985-2014

--- Module:   tst.c (C)
                _
        double d;
tst.c  5  Note 958: Padding of 7 byte(s) is required to align member on 8 byte
    boundary
    _
    } f = { 1, 2.0, 3 };
tst.c  7  Note 959: Nominal struct size (18 bytes) is not an even multiple of
    the maximum member alignment (8 bytes)
tst.c  7  Note 958: Padding of 6 byte(s) is required to align end of struct on
    8 byte boundary

Upvotes: 1

Hasturkun
Hasturkun

Reputation: 36422

You can use pahole to output information about holes in structures and optionally attempt packing them.

You may want to read "Poke-a-hole and friends" and the pahole announcement for more information

Upvotes: 7

Roee Gavirel
Roee Gavirel

Reputation: 19473

I Don't know any automatic tool, but this could be helpful example:

#include <stddef.h>

struct test {
  typea a;
  typeb b;
  typec c;
};

int gapB = offsetof(struct test, b) - (offsetof(struct test, a) + sizeof(typea));
int gapC = offsetof(struct test, c) - (offsetof(struct test, b) + sizeof(typeb));

printf("Gap of b:%d/n", gapB);
printf("Gap of c:%d/n", gapC);

*Note: you will have to do so for each two members in your stuck.

Upvotes: 1

Blagovest Buyukliev
Blagovest Buyukliev

Reputation: 43558

You can detect such "holes" via the offsetof macro:

#include <stddef.h>

struct test {
  char a;
  int b;
};
...
printf("%zu", offsetof(struct test, b));

If this prints more than 1, b obviously has alignment requirements and the compiler produces a gap in between.

Obviously this happens at runtime, not at compile-time, but you can write a script that produces a similar source file, compiles and runs it before the rest of your project, and then, based on the output you do further decisions on how to build your project.

I don't think any compiler provides a facility to notify you about that.

Upvotes: 0

Alexey Frunze
Alexey Frunze

Reputation: 62106

One way of finding such holes without analyzing the source code and without adding checks to it (using offsetof() and the like) would be to extract the symbol/debug information from the object/executable/symbol files with some tool and look at the defined structures and members in them, their offsets and sizes and see if everything adds up. Unions will complicate things, though.

Upvotes: 0

Ernest Friedman-Hill
Ernest Friedman-Hill

Reputation: 81724

You could explore this question by writing probe code for a particular struct using sizeof and &; if sizeof the nth member isn't equal to the address of the next member minus the address of that member, there's a hole.

Upvotes: 0

Related Questions