gcc 或 clang(或任何其他编译器)中是否有办法吐出有关结构中是否有孔(内存对齐方式)的信息?
谢谢你。
ps:如果有其他方法,请告知我。
gcc 或 clang(或任何其他编译器)中是否有办法吐出有关结构中是否有孔(内存对齐方式)的信息?
谢谢你。
ps:如果有其他方法,请告知我。
您可以使用pahole
输出有关结构中的孔的信息,并可以选择尝试打包它们。
您可能想阅读“Poke-a-hole and friends”和pahole 公告以获取更多信息
我不知道任何自动工具,但这可能是有用的示例:
#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);
*注意:您必须为卡住的每两个成员执行此操作。
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
您可以通过为特定的struct
使用sizeof
和编写探测代码来探索这个问题&
;如果sizeof
第n 个成员的地址不等于下一个成员的地址减去该成员的地址,则存在漏洞。
offsetof
您可以通过宏检测此类“漏洞” :
#include <stddef.h>
struct test {
char a;
int b;
};
...
printf("%zu", offsetof(struct test, b));
如果这打印出超过1
,b
则显然有对齐要求,并且编译器会在两者之间产生间隙。
显然,这发生在运行时,而不是编译时,但是您可以编写一个脚本来生成类似的源文件,在项目的其余部分之前编译并运行它,然后,根据输出,您可以进一步决定如何构建你的项目。
我认为任何编译器都没有提供通知您的工具。
在不分析源代码且不添加检查(使用 offsetof() 等)的情况下找到此类漏洞的一种方法是使用一些工具从对象/可执行文件/符号文件中提取符号/调试信息并查看定义结构和其中的成员,它们的偏移量和大小,看看是否一切都加起来了。不过,工会会使事情复杂化。
您需要一个能够理解 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;
}