【发布时间】:2021-10-14 01:03:18
【问题描述】:
在我的程序中,在 linux 上的嵌套结构上使用 _Decimal128 时会发生 coredump。
当满足以下所有条件时,就会发生这种情况。
首先,#pragma pack(8) 声明。
第二,第三个嵌套结构。
第三,_Decimal128类型地址作为函数的参数。
我正在寻找导致核心转储的原因。
开发环境为Redhat 8.3.1,编译成gcc。
示例代码如下。
#include <stdio.h>
#pragma pack(8) // without this line, it is success
struct _c {
int c1;
_Decimal128 c2;
};
struct _b {
int b1;
_Decimal128 b2;
struct _c b3; //3rd nested structure
};
struct _a {
int a1;
_Decimal128 a2;
struct _b a3; // 2nd nested structure
};
void func1(struct _c *cptr)
{
if (cptr->c2 == 0) // if argument type is structure, it is success
printf("[func1]\n");
}
void func2(_Decimal128 *ptr)
{
if (*ptr == 0) // if argument type is _Decimal128, it occurs coredump
printf("[func2]\n");
}
int main()
{
struct _a a;
struct _b b;
_Decimal128 t = 0;
b.b2 = t;
b.b3.c2 = t;
a.a3 = b;
func1(&a.a3.b3); // if argument is 3rd structure address, it is success
func2(&a.a3.b2); // if argument is _Decimal128 address of 2rd structure, it is sunccess
func2(&a.a3.b3.c2); // if argument is _Decimal128 address of 3rd structure, it occurs coredump
}
结果是,
[func1]
[func2]
Memory fault(coredump)
如果我从上面的源代码中删除#pragma pack(8)这一行,结果如下。
[func1]
[func2]
[func2]
【问题讨论】:
-
GCC 的哪个版本?似乎在没有更改 Godbolt 的 gcc 11.2 的情况下工作正常。 godbolt.org/z/9o75efq4e
-
不确定编译后的汇编代码,但似乎是因为 1.
#pragma pack(8)破坏了_Decimal128的对齐规则。 2.使用结构指针很好,因为它通知编译器_Decimal128由于未对齐而不能直接使用,应该像复制一样正确处理。 3. 使用_Decimal128*并不顺利,因为编译器会假定这是_Decimal128的有效(对齐)指针,而实际上不是。 -
@AKX 看起来优化非常聪明,它省略了函数的调用。
-
@AKX 您的示例仍然很有趣,因为它表明
movdqu(不会导致未对齐错误)在函数func1中用于从内存中加载值,而movdqa(导致错位错误)在函数func2中使用。 -
@AKX 参数在使用
movdqa和-O0之前被复制到正确对齐的堆栈中。
标签: c linux decimal redhat coredump