我有一个employee实例化的结构定义monica。结构看起来像这样
struct __attribute__((aligned(2))) employee {
int salary; // 4 bytes
int age; // 4 bytes
} monica;
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,我强制将结构对齐,2但 gcc 不会将结构对齐设置为 2,也不会引发错误。我尝试使用alignof宏(include <stdalign.h>)打印结构的对齐方式,该宏4作为结构的对齐方式返回。为什么 gcc 不能将结构的对齐方式设置为小于其字段之一的最大对齐方式的值。
我尝试通过另外添加一个指针作为结构中的字段来重现该问题。在将指针添加为字段时,我注意到 gcc 不允许我使用__attribute__((aligned(x))).
1GCC 允许我通过使用设置结构的对齐方式__attribute__((packed)),但它仍然不允许我1通过使用设置对齐方式__attribute__((aligned(1)))。为什么会发生这种情况?
海湾合作委员会 x86 v7.1.1
我们假设有一个 32 位 CPU 和 2 字节short。我知道 4 字节int需要在 4 的倍数地址处对齐,以避免额外读取。
问题:
0x1读取。0x0那么,为什么 Shorts 需要以 2 的倍数地址对齐呢?0x2,为什么它会被认为是对齐和高效的,因为CPU只能从0x0读取并丢弃前两个字节?有一个问题与此非常相似,但是,答案仅告诉我们short结构体和独立变量中的对齐要求是相同的。还有一条获得 2 票赞成的评论说:
在许多机器上,当数量是 N 字节对齐时,访问 N 字节数量(至少是 {1, 2, 4, 8, 16} 中的 N)的效率最高。生活就是这样;习惯它,因为我怀疑芯片制造商会仅仅因为你认为它不应该是这样而改变它。
但为什么?
我读过一些有关内存对齐的问题,但没有找到与我的问题相关的任何答案。
这里我有2个问题:
struct MyData
{
short Data1;
short Data2;
short Data3;
};
Run Code Online (Sandbox Code Playgroud)
为什么对齐方式是MyData等于2而不是6 == sizeof(MyData)?是否有任何特定原因导致struct使用与其他基元类型不同的方法来计算对齐方式?
根据微软的Alignment文档:
如果地址的对齐方式为 Xn+0,则称该地址与 X 对齐
这是否意味着只有当对象的MyData地址是其对齐方式的倍数时才对齐(2在本例中就是这样)?如果是这样,那么我们可以在内存中分配的对齐对象越大struct,对齐的对象就越少吗?MyData我的假设正确吗?
编辑:
这是SSE2编译器错误的后续内容
这是我之前遇到的真正的错误,并通过更改Michael Burr建议的_mm_malloc声明在下面转载:
SO.exe中0x00415116处的未处理异常:0xC0000005:访问冲突读取位置0xffffffff.
在线 label: movdqa xmm0, xmmword ptr [t1+eax]
我正在尝试动态分配t1,t2并且根据本教程,我使用过_mm_malloc:
#include <emmintrin.h>
int main(int argc, char* argv[])
{
int *t1, *t2;
const int n = 100000;
t1 = (int*)_mm_malloc(n*sizeof(int),16);
t2 = (int*)_mm_malloc(n*sizeof(int),16);
__m128i mul1, mul2;
for (int j = 0; j < n; j++)
{
t1[j] = j;
t2[j] = (j+1);
} // set temporary variables to random values
_asm
{ …Run Code Online (Sandbox Code Playgroud) 假设我们有一个具体的类A和一个抽象类B.
考虑一个具体的C,它继承自A和B,并实现B:
class C : public A, public B
{
/* implementation of B and specific stuff that belongs to C */
};
Run Code Online (Sandbox Code Playgroud)
现在我定义一个签名是什么的函数 void foo(B* b);
这是我的代码,我可以假设每个指向B的指针都是A和B.在foo的定义中,如何获得指向A的指针?一个讨厌但有效的技巧是将指针对齐,如下所示:
void foo(B* b)
{
A* a = reinterpret_cast<A*>(reinterpret_cast<char*>(b) - sizeof(A));
// now I can use all the stuff from A
}
Run Code Online (Sandbox Code Playgroud)
请记住,C没有超类型,实际上,有许多类似于C的类,只有A和B.可以自由地质疑我的逻辑和这个设计样本,但问题只是关于指针对齐.
所以我一直在忙着编写自己的自定义内存分配器,但是我遇到了一些我不理解的奇怪行为.
考虑以下代码:
void* PointerUtil::AlignForward(void* address, const uint8_t& alignment)
{
return (void*)(((uintptr_t)(address) + (uintptr_t)(alignment - 1)) & (uintptr_t)(~(alignment - 1)));
}
Run Code Online (Sandbox Code Playgroud)
这应该采用指针和对齐要求,并修改指针使其在正向(正向)上正确对齐.
但是,当我这样测试时:
int address = 1240;
std::cout << (uintptr_t)memory::PointerUtil::AlignForward((void*)((uintptr_t)address), 512) << std::endl;
std::cout << (uintptr_t)memory::PointerUtil::AlignForward((void*)((uintptr_t)address), 256) << std::endl;
std::cout << (uintptr_t)memory::PointerUtil::AlignForward((void*)((uintptr_t)address), 128) << std::endl;
std::cout << (uintptr_t)memory::PointerUtil::AlignForward((void*)((uintptr_t)address), 64) << std::endl;
std::cout << (uintptr_t)memory::PointerUtil::AlignForward((void*)((uintptr_t)address), 32) << std::endl;
Run Code Online (Sandbox Code Playgroud)
我得到的输出是这样的:
0
0
1280
1280
1248
Run Code Online (Sandbox Code Playgroud)
这似乎不对.它应该是:
1536
1280
1280
1280
1248
Run Code Online (Sandbox Code Playgroud)
这里出了什么问题?
试图回答另一个问题,我提出了一个解决方案,用于std::memcpy()将通用类型存储在chars 的缓冲区中.
我怀疑存储POD可能存在内存对齐问题(我知道有非POD类型,因为std::string非常非常危险).
简而言之:以下程序存在内存对齐问题?
如果它们是,那么可以写一些类似的东西(将POD值存储在char缓冲区中)是安全的吗?如何?
#include <cstring>
#include <iostream>
int main()
{
char buffer[100];
double d1 { 1.2 };
std::memmove( buffer + 1, & d1, sizeof(double) );
double d2;
std::memmove( & d2, buffer + 1, sizeof(double) );
std::cout << d2 << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud) operator new在 C++ 中,分配和初始化内存(通过调用默认构造函数)。如果我想要内存未初始化怎么办?在这种情况下如何分配内存?
malloc例如,在 CI 中可以使用它只会分配内存,而不是初始化它。
我有一个8字节对齐的结构,但是当我连续定义这种类型的某些变量但不在数组中时,它似乎是16字节对齐.我的问题是,编译器是否为某种目的增加了它的对齐?
我的测试代码是:
#include <stdio.h>
#include <stdint.h>
struct a{
long l[3];
};
struct a a1;
struct a a2;
struct a a3;
int main(){
printf("%lx\n", (uintptr_t)&a1);
printf("%lx\n", (uintptr_t)&a2);
printf("%lx\n", (uintptr_t)&a3);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出是:
601030
601050
601070
Run Code Online (Sandbox Code Playgroud) 我有这个代码:
double a[bufferSize];
double b[voiceSize][bufferSize];
double c[voiceSize][bufferSize];
...
inline void AddIntrinsics(int voiceIndex, int blockSize) {
// assuming blockSize / 2 == 0 and voiceIndex is within the range
int iters = blockSize / 2;
__m128d *pA = (__m128d*)a;
__m128d *pB = (__m128d*)b[voiceIndex];
double *pC = c[voiceIndex];
for (int i = 0; i < iters; i++, pA++, pB++, pC += 2) {
_mm_store_pd(pC, _mm_add_pd(*pA, *pB));
}
}
Run Code Online (Sandbox Code Playgroud)
但是,"有时",它提高访问内存冲突,我认为它是由于缺少我的3个数组的内存对齐的a,b和c.
但是,由于我操作__m128d(使用__declspec(align(16))),当我转换为指针时,是否保证对齐? …