gpt4 book ai didi

c++ - 使用 g++7 构建的代码因访问未对齐的内存而崩溃

转载 作者:太空狗 更新时间:2023-10-29 21:33:03 27 4
gpt4 key购买 nike

当我尝试运行使用 g++ 和优化 -O2 构建的程序时,这是一种奇怪的行为。使用:

  • g++-7 (Ubuntu 7.3.0-16ubuntu3) 7.3.0
  • 内核 4.15.0-36-generic

我有两个成员的结构:

struct A {                                   
uint8_t m8;
Int128 m128;
};

Int128 是:

// #pragma pack(push, 1)               
struct Base128 {
__int128_t v{0};
};
// #pragma pack(pop)

#pragma pack(push, 1)
struct Int128: Base128 {
Int128();
};
#pragma pack(pop)

Base128 显式未打包,但 Int128 以对齐 1 打包请注意,Base128 具有显式成员初始化,而 Int128 在另一个翻译单元中具有手动定义的空主体构造函数(以避免内联)。

当我将 Base128 打包更改为与 Int128 相同时,程序不会崩溃。

似乎编译器生成了无效指令:MOVAPS 而不是 MOVUPS 以访问构造函数中的 __int128_t 成员:

00000000000006b0 <_ZN6Int128C1Ev>:
6b0: 66 0f ef c0 pxor %xmm0,%xmm0
6b4: 55 push %rbp
6b5: 48 89 e5 mov %rsp,%rbp
6b8: 0f 29 07 movaps %xmm0,(%rdi)
6bb: 5d pop %rbp
6bc: c3 retq
6bd: 0f 1f 00 nopl (%rax)

反之亦然:

00000000000006b0 <_ZN6Int128C1Ev>:
6b0: 66 0f ef c0 pxor %xmm0,%xmm0
6b4: 55 push %rbp
6b5: 48 89 e5 mov %rsp,%rbp
6b8: 0f 11 07 movups %xmm0,(%rdi)
6bb: 5d pop %rbp
6bc: c3 retq
6bd: 0f 1f 00 nopl (%rax)

你知道我做错了什么吗?

源代码:

测试.h:

#pragma once

#include <cstdint>

//#pragma pack(push, 1) // it fixes problem
struct Base128 {
__int128_t v{0};
};
//#pragma pack(pop)

#pragma pack(push, 1)
struct Int128: Base128 {
Int128();
};
#pragma pack(pop)

struct A {
uint8_t m8;
//Int128 __attribute__((aligned(16))) m128; // it fixes problem
Int128 m128;
};

测试.cpp:

#include "test.h"

// Int128::Int128() : Base128{0} {} // Fixes (why ?!)
Int128::Int128() {}

主要.cpp:

#include "test.h"
int main() {
A a;
return 0;
}

构建和运行:

g++-7 --save-temps -Wall -Wextra -std=c++14 -O2 -g main.cpp test.cpp && ./a.out

Source code on gitlab is here .它可以按如下所示构建和运行:

./build.sh # build and run (crashes)
./build.sh [1..5] # where 1..5 -- different fixes

最佳答案

来自documentation alignas,据我所知相当于 gcc 的打包属性:

If the strictest (largest) alignas on a declaration is weaker than the alignment it would have without any alignas specifiers (that is, weaker than its natural alignment or weaker than alignas on another declaration of the same object or type), the program is ill-formed:

struct alignas(8) S {};
struct alignas(1) U { S s; }; // error: alignment of U would have been 8 without alignas(1)

此示例实际上与您的示例完全相同(将类的父级视为其第一个成员)。

因此我们可以肯定地说您的程序格式错误,从而调用未定义行为。您的大多数变通办法基本上都可以被忽略,因为基本上只是“运气”。无需解释它们为何起作用。

有趣的是,在代码中交换标准 alignas() 时,gcc 仍然没有报错,但 clang 开始正确报告错误:https://gcc.godbolt.org/z/EEErXg

编辑: alignas() 和 gcc 打包的等价性引用:

GCC 表示它是 MSVC 功能的直接端口:https://gcc.gnu.org/onlinedocs/gcc-4.8.0/gcc/Structure_002dPacking-Pragmas.html

Microsoft 说 alignas() 是同一件事:https://msdn.microsoft.com/en-us/library/2e70t5y1.aspx

关于c++ - 使用 g++7 构建的代码因访问未对齐的内存而崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52894849/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com