c - linux c程序中发生Coredump(Redhat 8.3.1)
问题描述
在我的程序中,_Decimal128
在 linux 上的嵌套结构上使用时会发生 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]
解决方案
#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), %xmm0
func2:
subq $8, %rsp
movdqa .LC1(%rip), %xmm1
movdqa (%rdi), %xmm0
在此示例中,该movdqu
指令用于加载_Decimal128
函数中的值func1
。movdqu
可以使用未对齐的内存。
另一方面,该movdqa
指令用于_Decimal128
函数中的值func2
。movdqa
在尝试使用未对齐的内存时生成一般保护异常。
这表明func1
可以使用未对齐的内存,而func2
在此示例中不能。
推荐阅读
- python - Python 矩阵赛博朋克求解器
- android - Android TWA 资产链接验证适用于 APK 文件,但不适用于 AAB
- python - 如果数据类型是元组,我如何过滤数据框?
- python - 将内部列表分配给新变量 - Python
- sql - 如何从 ASP.NET MVC 控制器中的数组计算运行平衡?
- python - Matplotlib 单击时删除行
- redux-toolkit - Redux 工具包切片。场缩减器中的纯函数
- javascript - 如何根据ID获取文档下的所有数据
- php - 无法使用 localhost 和 amps 登录
- android - 在 mockk 中模拟嵌套属性