查找C结构中由于对齐而出现的孔

查找C结构中由于对齐而出现的孔,c,struct,memory-alignment,C,Struct,Memory Alignment,在gcc或clang(或任何其他编译器)中,有没有一种方法可以吐出关于结构中是否有漏洞(内存对齐)的信息 多谢各位 附言:如果有其他方法,请务必通知我 您可以通过使用sizeof和&为特定的结构编写探测代码来探索这个问题;如果第n个成员的sizeof不等于下一个成员的地址减去该成员的地址,则存在一个洞。您可以通过offsetof宏检测此类“洞”: #include <stddef.h> struct test { char a; int b; }; ... printf("

在gcc或clang(或任何其他编译器)中,有没有一种方法可以吐出关于结构中是否有漏洞(内存对齐)的信息

多谢各位


附言:如果有其他方法,请务必通知我

您可以通过使用
sizeof
&
为特定的
结构编写探测代码来探索这个问题;如果第n个成员的
sizeof
不等于下一个成员的地址减去该成员的地址,则存在一个洞。

您可以通过
offsetof
宏检测此类“洞”:

#include <stddef.h>

struct test {
  char a;
  int b;
};
...
printf("%zu", offsetof(struct test, b));
#包括
结构测试{
字符a;
int b;
};
...
printf(“%zu”,偏移量(结构测试,b));
如果打印的内容超过
1
b
显然有对齐要求,编译器会在两者之间产生间隙

显然,这发生在运行时,而不是编译时,但您可以编写一个脚本,生成类似的源文件,在项目的其余部分之前编译并运行它,然后根据输出进一步决定如何构建项目


我认为任何编译器都不会提供通知您这一点的工具。

一种在不分析源代码和不向源代码添加检查的情况下查找此类漏洞的方法(使用offsetof()等)将是使用一些工具从对象/可执行文件/符号文件中提取符号/调试信息,查看其中定义的结构和成员、它们的偏移量和大小,并查看是否所有内容都在一起。不过,工会会使事情复杂化。

我不知道任何自动工具,但这可能是一个有用的例子:

#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);
#包括
结构测试{
a型;
b型;
c型;
};
int gapB=偏移量(结构测试,b)-(偏移量(结构测试,a)+大小(类型a));
int gapC=偏移量(结构测试,c)-(偏移量(结构测试,b)+大小(类型b));
printf(“b的间隙:%d/n”,gapB);
printf(“c的间隙:%d/n”,gapC);
*注意:您必须为卡滞结构中的每两个构件执行此操作。

您可以使用来输出有关结构中孔的信息,并可以选择尝试对其进行打包


您可能需要阅读,有关更多信息,Gimpel的FlexeLint/PClint可以这样做

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

    return f.c;
}
它将报告

$ 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

您需要一个能够理解c/c++结构并包含必要文件的解析器

正如@roee gavirel所回答的,我认为更简单的解决方案是创建一个测试程序来打印偏移量

#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;
}
#包括
#包括
类型定义结构tData{
长id;/*8字节*/
字符名[8];/*8字节*/
浮动工资;/*4字节*/
}tData;
tdatad;
int main()
{
size_t s_tData=sizeof(tData);
size_t s_id=sizeof(d.id);
size_t s_name=sizeof(d.name);
工资大小=工资大小(d.salary);
printf(“sizeof(tData)=%zu\n\n”,sizeof(d));
printf(“'id'位于=%3zu,占用%zu字节\n”,
偏移量(tData,id),s_id);
printf(“'name'位于=%3zu,占用%zu字节\n”,
偏移量(tData、名称)、s_名称);
printf(“'salary'位于=%3zu,占用%zu字节\n”,
抵销(tData、工资)、s_工资);
printf(“\n”);
如果(s_tData!=s_id+s_姓名+s_薪水)
printf(“有/有洞”);
返回0;
}

是否有一种方法可以自动执行此操作?仅调查结构可能不够,代码中甚至CFLAGS中都有对齐选项。你在说多少行代码?结构是否可能用于将数据存储在文件中?我的问题主要是学术性质的,但我想测试几百万个。这些结构主要是CAD/CAE对象。所以我想没有编译器开关:)。然而,这是一个有趣的(至少对我来说)主题。如果我想分析对象文件,我从哪里开始?@John:首先看看是否有任何工具可以读取符号/调试信息,并以某种人类可读的形式将其转储。如果没有,请查看您拥有源代码的哪些工具使用这些数据,并在此基础上开发自己的工具。和往常一样,请参阅有关文件格式的文档。这就是
pahole
等人所做的。这里有一些编写结构的已知技术,因此您几乎可以确保它们不包含填充。如果这有帮助的话,让我知道,我会把细节告诉你。谢谢。我想这就是我要找的。