我正在尝试在c ++结构中打包数据.
我的结构有这样的布局:
struct structName
{
int16_t member1;
int32_t member2;
uint32_t member3;
uint32_t member4;
uint32_t member5;
etc
}__attribute__((packed));
Run Code Online (Sandbox Code Playgroud)
使用offsetof($structname, $membername)我得到正确的数据偏移量(0,2,6,10,14 ...),但是当我按成员名访问数据时,我得到4字节偏移的数据(0,4,8, 12,16 ......)好像结构没有打包.
是
} __attribute__((packed));
Run Code Online (Sandbox Code Playgroud)
构建一个struct的正确方法是什么?..
readelf -l /bin/bash 给我这个:
程序标题:
类型偏移VirtAddr PhysAddr
FileSiz MemSiz标志对齐
PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040
0x00000000000001f8 0x00000000000001f8 RE 8
INTERP 0x0000000000000238 0x0000000000400238 0x0000000000400238
0x000000000000001a 0x000000000000001a R 1
[请求程序解释器:/lib/ld-linux-x86-64.so.2]
加载0x0000000000000000 0x0000000000400000 0x0000000000400000
0x00000000000aeef4 0x00000000000aeef4稀土200000
加载0x00000000000afde0 0x00000000006afde0 0x00000000006afde0
0x0000000000003cec 0x000000000000d3c8 读写200000
动态0x00000000000afdf8 0x00000000006afdf8 0x00000000006afdf8
0x0000000000000200 0x0000000000000200读写8
注意0x0000000000000254 0x0000000000400254 0x0000000000400254
0x0000000000000044 0x0000000000000044 R 4
GNU_EH_FRAME 0x000000000009dbc0 0x000000000049dbc0 0x000000000049dbc0
0x0000000000002bb4 0x0000000000002bb4 R 4
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000读写8
GNU_RELRO 0x00000000000afde0 0x00000000006afde0 0x00000000006afde0
0x0000000000000220 0x0000000000000220 R 1
为什么在某些细分市场中MemSiz不等于?包含但不包含的存储区应该怎么办?FileSizLOADMemSizFileSiz
我有一个代码片段。该代码段仅加载 2 个数组并使用 SSE 计算它们之间的点积。
代码在这里:
using namespace std;
long long size = 3200000;
float* _random()
{
unsigned int seed = 123;
// float *t = malloc(size*sizeof(float));
float *t = new float[size];
int i;
float num = 0.0;
for(i=0; i < size; i++) {
num = rand()/(RAND_MAX+1.0);
t[i] = num;
}
return t;
}
float _dotProductVectorSSE(float *s1, float *s2)
{
float prod;
int i;
__m128 X, Y, Z;
for(i=0; i<size; i+=4)
{
X = _mm_load_ps(&s1[i]);
Y = _mm_load_ps(&s2[i]);
X = …Run Code Online (Sandbox Code Playgroud) 这个小代码片段与 g++ 6.2.0 和 clang++ 3.8.1 的段错误:
clang++ -std=c++11 -O3 -mavx -pthread 或者 g++ -std=c++11 -O3 -mavx -pthread
#include <thread>
#include <iostream>
class alignas(32) AlignedObject {
public:
float dummy[8];
};
int main() {
while (true) {
std::thread([](){
AlignedObject x;
std::cout << &x;
std::thread([x](){
std::cout << &x;
}).join();
}).join();
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
查看反汇编,两个编译器都插入vmovaps了失败的指令,这表明某处编译器生成的对象没有正确对齐。-mavx由于不再使用该指令,因此删除它可以正常工作。这是编译器错误还是该代码依赖于未定义的行为?
我__int128用作struct的成员.它可以找到-O0(没有优化).
但是,如果启用了优化(-O1),则会因段故障而崩溃.
它在指令处崩溃movdqa,需要将var对齐16,而地址的分配malloc()仅由8对齐.
我尝试禁用SSE优化-mno-sse,但无法编译:
/usr/include/x86_64-linux-gnu/bits/stdlib-float.h:27:1: error: SSE register return with SSE disabled
Run Code Online (Sandbox Code Playgroud)
所以,我能做些什么,如果我想使用__int128和-O1两者兼而有之?
在此先感谢吴
顺便说一下,如果__int128仅在堆栈上使用(不在堆上),似乎没问题.
====编辑====
对不起,我没说实话.
其实我没用过malloc().我使用了一个内存池lib,它返回8对齐的地址.我说malloc()只是为了让事情变得简单.
经过测试,我已经知道它malloc()与16对齐.并且__int128成员也在结构中对齐16.
所以问题是我的内存池lib.
非常感谢.
这本书说如下:
对于 Knights Landing,当数据起始地址位于 64 字节边界时,内存移动是最佳的。
Q1. 有没有办法在 C++ 代码中动态查询处理器,以了解n当前运行应用程序的处理器的最佳字节边界是什么?这样,代码就可以移植了。
书中进一步指出:
作为程序员,我们最终有两项工作:(1)对齐我们的数据;(2)确保编译器知道它是对齐的。
(假设对于下面的问题,我们知道处理器的最佳数据是从 64 字节边界开始。)
这个“数据”到底是什么?
假设我有一堂课:
class Class1_{
private:
int a;//4 bytes
double b;//8 bytes
std::vector<int> potentially_longish_vector_int;
std::vector<double> potentially_longish_vector_double;
double * potentially_longish_heap_array_double;
public:
//--stuff---//
double * return_heap_array_address() {return potentially_longish_heap_array_double;}
}
Run Code Online (Sandbox Code Playgroud)
假设我还有原型化的函数:
void func1(Class1_& obj_class1);
void func2(double* array);
Run Code Online (Sandbox Code Playgroud)
也就是说,通过引用func1接收一个对象,并调用为Class1_func2func2(obj_class1.return_heap_array_address());
为了与数据应该适当边界对齐的建议保持一致,obj_class1它本身应该是 64 字节边界对齐以实现 的有效运行func1()吗?应该potentially_longish_heap_array_double对齐 64 字节边界才能有效运行吗func2()?
对于作为 STL 容器的类的其他数据成员的对齐,此处的线程建议如何完成所需的对齐。
Q2。那么,对象本身以及其中的所有数据成员是否需要适当对齐?
c++ simd vectorization memory-alignment compiler-optimization
16 字节atomic<>变量是否在 16 字节边界上自动对齐,从而允许编译器/运行时库有效地使用 x86CMPXCHG16B指令?或者我们应该根据风格总是手动指定alignas(16)所有这些变量?
为什么placement new 依赖于#include <iostream>?
听起来很荒谬?好吧,此代码仅在注释 include 时才编译:
// #include <iostream>
struct Alignas { void* ptr; };
alignas(Alignas) static char storage[sizeof(Alignas)];
int main() { new(storage) Alignas; }
Run Code Online (Sandbox Code Playgroud)
Gcc 错误(与 Clang 相同):
alignas.cpp:7:27: error: no matching function for call to ‘operator new(sizetype, char [8])’
7 | int main() { new(storage) Alignas; }
| ^~~~~~~
<built-in>: note: candidate: ‘void* operator new(long unsigned int)’
<built-in>: note: candidate expects 1 argument, 2 provided
<built-in>: note: candidate: ‘void* operator new(long unsigned int, std::align_val_t)’
<built-in>: …Run Code Online (Sandbox Code Playgroud) 由于 ARM64 中缺少 PUSH 和 POP 指令,我在理解 SP 在 ARM64 中的工作方式时遇到了问题。
如果我要 PUSH/POP,SP 是否会减少/增加 4、8 或 16 个字节?
我正在阅读文档说堆栈帧必须按 16 字节对齐,但是当我调试时,情况似乎并非如此。
堆栈对齐在 ASMx64 中是如何工作的?什么时候需要在函数调用前对齐堆栈,需要减去多少?
我不明白这样做的目的是什么。我知道还有其他关于这个的帖子,但对我来说还不够清楚。例如:
extern foo
global bar
section .text
bar:
;some code...
sub rsp, 8 ; Why 8 (I saw this on some posts) ? Can it be another value ? Why do we need to substract?
call foo ; Do we need to align stack everytime we call a function?
add rsp, 8
;some code...
ret
Run Code Online (Sandbox Code Playgroud) assembly x86-64 calling-convention memory-alignment stack-pointer