在我的程序中,在linux上的嵌套结构上使用_Decimal128时会出现coredump。
当满足以下所有条件时,就会发生这种情况。
首先是#pragma pack(8)声明。
第二,第三嵌套结构。
第三,_Decimal128 类型address作为函数的参数。
我在找一个导致核衰竭的原因。
开发环境为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]发布于 2021-08-10 13:30:01
#pragma pack(8)会告诉编译器,结构的成员应该对齐为8个字节,而忽略了每种类型的对齐要求。
_Decimal128可能是16字节类型,其对齐要求可能是16字节.
使用指向结构struct _c *cptr的指针,编译器可以知道成员使用了非常规的对齐方式,并且可能需要某种特殊的方式来处理_Decimal128成员。
另一方面,直接使用指向_Decimal128的指针时,编译器将假定指针是指向_Decimal128成员的有效(通常对齐)指针。因此,当传递的不是指向_Decimal128的普通指针时,它可能会失败。
让我们用一些例子来验证这个语句。
首先,让我们检查一下_Decimal128成员的对齐要求和地址:
#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
};
int main(void) {
struct _a a;
printf("sizeof(_Decimal128) = %d\n", (int)sizeof(_Decimal128));
printf("_Alignof(_Decimal128) = %d\n", (int)_Alignof(_Decimal128));
printf("&a = %p\n", (void*)&a);
printf("&a.a3.b3.c2 = %p\n", (void*)&a.a3.b3.c2);
return 0;
}sizeof(_Decimal128) = 16
_Alignof(_Decimal128) = 16
&a = 0x7fffee270d70
&a.a3.b3.c2 = 0x7fffee270da8在这种环境中,_Decimal128的对齐要求是16字节,但是成员_Decimal128 c的地址不能被16整除。
其次,这里是@AKX示例,它显示了Decimal128可以用函数func1 (使用指向结构的指针)和函数func2 (使用指向_Decimal128的指针)进行不同的处理:
func1:
subq $8, %rsp
movdqa .LC1(%rip), %xmm1
movdqu 8(%rdi), %xmm0func2:
subq $8, %rsp
movdqa .LC1(%rip), %xmm1
movdqa (%rdi), %xmm0在本例中,说明用于在函数func1中加载_Decimal128值。movdqu可以使用未对齐内存。
另一方面,说明用于函数func2中的_Decimal128值。movdqa在尝试使用未对齐内存时会生成一般保护异常。
这表明,在本例中,func1可以处理未对齐内存,而func2不能。
https://stackoverflow.com/questions/68727253
复制相似问题