Find holes in C structs due to alignment

懵懂的女人 提交于 2019-12-05 16:55:28

问题


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.


回答1:


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




回答2:


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.




回答3:


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



回答4:


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.




回答5:


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.




回答6:


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.




回答7:


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;
}


来源:https://stackoverflow.com/questions/7674127/find-holes-in-c-structs-due-to-alignment

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!