在将对象添加到数据结构之前,我试图确保对象对齐vector。响应警告warning C4316: 'Basic' : object allocated on the heap may not be aligned 16,我对该对象有以下内容Basic:
class Basic
{
public:
Basic();
~Basic();
};
Run Code Online (Sandbox Code Playgroud)
这是这里的标准对象。接下来,unique_ptr将a 分配给new的实例,Basic以获得这样做的好处。(与标准指针相反)
unique_ptr<Basic> e_Basic{new Basic()};
Run Code Online (Sandbox Code Playgroud)
我尝试对齐数据,以便以后可以避免对齐问题:
e_Basic.reset =_aligned_malloc((size_t)sizeof(Basic), (size_t)(16 + (sizeof(Basic) % 16))); //Verify alignment.
Run Code Online (Sandbox Code Playgroud)
最后将指针添加到vector数组中。
LocalBasicQueue.push_back(move(e_Basic));
Run Code Online (Sandbox Code Playgroud)
编译器说它是犹太洁食,但我的“胡扯什么?” 代码意识正在消失。这会导致指向(肯定)对齐代码的指针吗?
以这种方式声明( e_Basic.reset) 等于指针[由 ] 返回并调用它,分配新指针是否可以?_aligned_malloc()unique_ptr<>
CSAPP 解释说,SSE 指令对 16 字节数据块进行操作,并且需要内存地址是 16 的倍数。
但是和栈帧有什么关系呢?这是否意味着SSE指令在堆栈帧上运行?如果有的话,常用的指令是什么?
我有两个寄存器 w1 和 w2,我想将它们存储在堆栈上。我想将完整的单词w1和w2的一半存储到堆栈中。这是我的实现:
STR w1, [sp, #-8]!
STRH w2, [sp, #-8]!
Run Code Online (Sandbox Code Playgroud)
编译时,第一条指令运行良好,但第二条指令引发总线错误。我知道这是一些对齐问题,但我无法正确理解为什么会发生这种情况?
我正在针对 ARMv8(64 位)架构进行编译。
我正在编写一个跨平台应用程序,该应用程序可在 x86 机器上运行,但在实际 ARM 硬件(Raspberypi 2)上因“总线错误”而崩溃...
[ 4105.019037] Alignment trap: not handling instruction edd37a00 at [<00014218>]
[ 4105.019059] Unhandled fault: alignment exception (0x001) at 0x0002814e
[ 4105.028227] pgd = b736c000
[ 4105.033347] [0002814e] *pgd=3708d835, *pte=335d075f, *ppte=335d0c7f
Run Code Online (Sandbox Code Playgroud)
...但在Qemu中运行没有任何问题。
我运行此命令以在 Qemu 下运行的内核中启用 SIGBUS 信号和通知,但它似乎没有任何效果:
echo 5 > /proc/cpu/alignment[ 2 ]
如何在 Qemu(或其他免费模拟器)中模拟这些错误?我希望能够在 x86 机器上运行的持续集成环境中运行自动化测试,而我无法使用实际的硬件。或者,我可以租用 ARM 服务器,但我想避免这种情况。
稍后编辑以进一步澄清:在真实硬件上导致此问题的指令也在模拟器中执行,它似乎可以工作而不会触发任何异常。
我知道,一旦取消引用,带有对齐冲突的指针转换的结果就会调用未定义的行为。
\n但是仅用于地址计算(不取消引用)的指针转换怎么样?
\nvoid *addr_calc(single_byte_aligned_struct_t *ptr, uint32_t dword_offset)\n{\n uint32_t *dw_ptr = (uint32_t *)ptr;\n\n return dw_ptr + dword_offset;\n}\nRun Code Online (Sandbox Code Playgroud)\n我们假设 的ptr值为X。能保证一定addr_calc()会回来X + sizeof(uint32_t) * dword_offset吗?
我的假设是,但最近我在 C11 标准的J.2 节中看到了以下未定义行为
\n\n\n\xe2\x80\x94 两个指针类型之间的转换会产生不正确对齐的结果 (6.3.2.3)。
\n
如果我理解正确的话,转换本身会调用未定义的行为,而不仅仅是取消引用,这意味着在这种情况下,即使是指针算术也可能表现出不可预测的行为。我对吗?
\nc memory-alignment pointer-arithmetic undefined-behavior c11
GNU文档指出,它malloc在 64 位系统上与 16 字节倍数对齐。为什么是这样?
如果我的理解是正确的,寄存器和所有指令都对最大 8 字节宽的值进行操作。因此,似乎需要 8 字节对齐。
笔记:
x86_64我正在尝试实现一种多态数据结构,例如侵入式链表(我已经知道内核有一个 - 这更多的是学习经验)。
\n问题在于将嵌套结构转换为包含结构会导致gcc发出内存对齐警告。
具体情况如下:
\n// t.c\n#include <stdio.h>\n\nenum OL_TYPE { A, B, C };\n\nstruct base {\n enum OL_TYPE type;\n};\n\nstruct overlay {\n struct base base;\n int i;\n};\n\nstruct overlay2 {\n struct base base;\n float f;\n int i;\n // double d; // --> adding this causes a memory alignment warning\n};\n\nvoid testf(struct base *base) {\n if (base->type == A) {\n struct overlay *olptr = (struct overlay *)base;\n printf("overlay->i = %d\\n", olptr->i);\n } else\n if (base->type == B) {\n struct …Run Code Online (Sandbox Code Playgroud) 我们看一下代码
#include <stdint.h>
#pragma pack (push,1)
typedef struct test_s
{
uint64_t a1;
uint64_t a2;
uint64_t a3;
uint64_t a4;
uint64_t a5;
uint64_t a6;
uint64_t a7;
uint8_t b1;
uint64_t a8;
}test;
int main()
{
test t;
__atomic_store_n(&(t.a8), 1, __ATOMIC_RELAXED);
}
Run Code Online (Sandbox Code Playgroud)
由于我们有打包结构,a8 不是自然对齐的,也应该在不同的 64 字节缓存边界之间分割,但生成的程序集 GCC 12.2 是
main:
push rbp
mov rbp, rsp
mov eax, 1
mov QWORD PTR [rbp-23], rax
mov eax, 0
pop rbp
ret
Run Code Online (Sandbox Code Playgroud)
为什么它翻译成简单的MOV?在这种情况下 MOV 不是原子的吗?
添加:clang 16 调用原子函数的相同代码并转换为
main: # @main
push rbp
mov rbp, rsp
sub …Run Code Online (Sandbox Code Playgroud) 我在 cpp.sh 上进行了一个实验(没有特殊标志),其中字大小似乎是 4 个字节。在我的实验中,我在堆栈上初始化了两个 type 元素Data,一个只有一个字符的结构,并打印出它们的地址。我对两个 char 类型的变量做了同样的事情。
#include <iostream>
#include <bitset>
struct Data {
char c;
};
void PrintAddr(const void* ptr) {
std::cout << std::bitset<32>((unsigned int) ptr) << std::endl;
}
int main()
{
std::cout << "word size = " << sizeof(size_t) << std::endl;
std::cout << "sizeof = " << sizeof(Data) << std::endl;
std::cout << "alignof = " << alignof(Data) << std::endl;
std::cout << "Data addresses: " << std::endl;
Data a, b;
PrintAddr(&a);
PrintAddr(&b);
std::cout << "char …Run Code Online (Sandbox Code Playgroud) 我有一节课:
class CMatrix4f
{
public:
CMatrix4f();
public:
__declspec(align(16)) float m[16];
};
Run Code Online (Sandbox Code Playgroud)
此类使用SSE实现矩阵操作,因此m 必须对齐才能使其工作.它大部分时间都可以工作,但有时我会在执行SSE指令时遇到段错误,例如_mm_load_ps因为m不是16字节对齐.到目前为止,我无法理解它发生在哪些情况.
当我这样做CMatrix4f * dynamicMatrix = new CMatrix4f();,是dynamicMatrix.m保证对齐?
如果我有课:
class MatrixWrapper {
public:
MatrixWrapper();
CMatrix4f _matrix;
};
Run Code Online (Sandbox Code Playgroud)
然后做:
MatrixWrapper * dynamicMatrixWrapper = new MatrixWrapper();
Run Code Online (Sandbox Code Playgroud)
为dynamicMatrixWrapper._matrix.m保证对齐?
我已经阅读了关于路由的MSDN文章,但目前还不清楚它是否适用于动态分配.