gcc - ELF:为什么将struct变量放入64位系统中以32字节对齐的部分
问题描述
编码:
// test.c
#include <stdint.h>
typedef struct cgi
{
const char *cgi_name;
void *data;
uint32_t flags;
} cgi_t;
static cgi_t a, b, c;
编译它:
$ cc -c test.c
自述
$ readelf -a test.o
5: 0000000000000000 24 OBJECT LOCAL DEFAULT 3 a
6: 0000000000000020 24 OBJECT LOCAL DEFAULT 3 b
7: 0000000000000040 24 OBJECT LOCAL DEFAULT 3 c
太奇怪了,这 3 个变量被放置到与 0x20 对齐的地址。此行为使以下代码失败:
extern cgi_t __start_cgicalls, __stop_cgicalls;
cgi_t * lookup_cgi(const char *name) {
cgi_t *cgi_entry;
for (cgi_entry = &__start_cgicalls;
cgi_entry < &__stop_cgicalls; cgi_entry++) {
if (!strcmp(name, cgi_entry->cgi_name))
return cgi_entry;
}
return NULL;
}
我将注册的 cgi 条目放到 cgi 部分,然后查看它们,因为它们的偏移量错误,所以我在程序崩溃时查找它们。
===============
我通过强制 struct align 到 16 个字节来修复它。我发现一个材料说,
当结构大于 16 字节时,变量将被 algined 到 16 字节
typedef int (* cgicb_t)(struct http_req *req, struct http_res *res);
/* note: because we look up cgi entry based on array align (8 bytes in 64bits system)
but the variable may be put in section with different align (big struct is aligned to 16 bytes)
so, here we force the align to 16 bytes !!!
*/
typedef struct cgi
{
const char *cgi_name;
cgicb_t fn;
uint32_t flags;
} __attribute__ ((aligned (16))) cgi_t;
#define REGISTER_CGI(name, cb, flag) \
static cgi_t __cgicall##cb \
__attribute__((__section__("cgicalls"))) __attribute__((used)) \
= { \
.cgi_name = name, \
.fn = cb, \
.flags = flag, \
}
#define REG_CGI(cb) REGISTER_CGI(CGI_PATH #cb, cb, CGI_FLAG_PERM)
解决方案
太奇怪了,这3个变量被放置到与0x20对齐的地址
您的问题非常令人困惑,因为它与任何部分都无关。
您的问题似乎是:“为什么是a
,b
并且在什么c
时候相隔 32 个字节sizeof(cgi_t) == 24
?”。
你的假设a
,b
并且在节中c
互相跟随是无效的。编译器可以将它们按、或任何其他顺序放置,或者可以在它们之间放置一些其他数据。.bss
b
a
c
要明确定义顺序和位置,您必须声明它们的数组:static cgi_t cgicalls[3];
.
推荐阅读
- visual-studio - 最新版本 Visual Studio 不支持安装项目
- java - ListView 不与 JavaFX 一起显示
- express - 如何从 api-endpoint 在浏览器中显示使用 express/pdfkit 生成的 PDF
- java - Kotlin 1.4.30 Apache Beam 编译错误
- javascript - 未使用 Vue Chart JS 选项
- optimization - ScipyOptimizeDriver 中的 SLSQP 只执行一次迭代,耗时很长,然后退出
- php - 为什么我的 Symfony 5 项目中缺少 AbstractDashboardController
- android - 如何解决我的 kotlin 应用程序的这个黑屏问题?
- python - Raspberry Pi 按钮 LED 随机触发器
- google-cloud-dataflow - 谷歌云构建 python apache 光束数据流 yaml 文件