Странное поведение, когда я пытаюсь запустить программу, созданную с помощью 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
Beзаметил, что 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)
У вас есть идеи: что я делаю не так?
Исходный код:
test.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;
};
test.cpp:
#include "test.h"
// Int128::Int128() : Base128{0} {} // Fixes (why ?!)
Int128::Int128() {}
main.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
Исходный код на gitlab находится здесь .Он может быть построен и запущен, как указано ниже:
./build.sh # build and run (crashes)
./build.sh [1..5] # where 1..5 -- different fixes