Find holes in C structs due to alignment
Asked Answered
B

7

13

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.

Boccie answered 6/10, 2011 at 12:17 Comment(1)
There are known techniques to wrote structures so you could be virtually sure that they do not contain padding. If this would help, let me know and I'll fill you in on the details.Reptilian
F
7

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

Flak answered 6/10, 2011 at 13:17 Comment(0)
S
1

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.

Straticulate answered 6/10, 2011 at 13:2 Comment(0)
S
1

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
Stealthy answered 18/6, 2015 at 14:37 Comment(0)
H
0

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.

Halhalafian answered 6/10, 2011 at 12:20 Comment(0)
B
0

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.

Build answered 6/10, 2011 at 12:22 Comment(3)
Is there a way to automate this ?Boccie
Investigating the structs may not be enough, there are align options, either in the code or even in the CFLAGS. About how much lines of code are you talking? Is it possible that the structs are used to store data in files?Stokehold
My question is mostly of academic nature, but I would like to test a couple of millions LOC. The stucts are mostly CAD/CAE objects.Boccie
Y
0

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.

Yon answered 6/10, 2011 at 12:26 Comment(3)
So i guess there is no compiler switch :). It is an interesting (to me at least) subject however. Where would I start, if I wanted to analyze object files ?Boccie
@John: first see if there any tools that can read the symbol/debug info and dump it in some human-readable form. If not, see what tools, for which you have source code, consume this data and develop your own based on that. And, as usual, see the documentation on the file formats.Yon
this is what pahole et al doThuggee
H
0

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;
}
Huntlee answered 10/3, 2018 at 10:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.