在分配了new []的阵列上使用avx时出现分段错误(核心转储) [英] Segmentation fault (core dumped) when using avx on an array allocated with new[]
问题描述
当我在Visual Studio 2015中运行此代码时,代码可以正常运行,但是代码在代码块中生成以下错误:分段错误(核心已转储).我也用同样的错误在ubuntu中运行了代码.
#include <iostream>
#include <immintrin.h>
struct INFO
{
unsigned int id = 0;
__m256i temp[8];
};
int main()
{
std::cout<<"Start AVX..."<<std::endl;
int _size = 100;
INFO *info = new INFO[_size];
for (int i = 0; i<_size; i++)
{
for (int k = 0; k < 8; k++)
{
info[i].temp[k] = _mm256_setr_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31);
}
}
std::cout<<"End AVX."<<std::endl;
return 0;
}
问题在于,在C ++ 17之前,new
和delete
不遵守待分配类型的对齐方式.如果您通过此简单函数查看生成的程序集:
INFO* new_test() {
int _size = 100;
INFO *info = new INFO[_size];
return info;
}
您将看到,使用C ++ 17之前的任何内容编译时,会调用operator new[](unsigned long)
,而对于C ++ 17,将调用operator new[](unsigned long, std::align_val_t)
(第二个参数传递了32
) .
在Godbolt上玩.
如果不能使用C ++ 17,则可以覆盖operator new[]
(和operator delete[]
-并且还应该覆盖operator new
和operator delete
...):
struct INFO {
unsigned int id = 0;
__m256i temp[8];
void* operator new[](size_t size) {
// part of C11:
return aligned_alloc(alignof(INFO), size);
}
void operator delete[](void* addr) {
free(addr); // aligned_alloc is compatible with free
}
};
如果使用-DOVERWRITE_OPERATOR_NEW
进行编译,则这是前面的Godbolt示例的一部分.
请注意,使用std::vector
(或任何其他std
-容器)时,这不能解决对齐问题,因为您需要将对齐的分配器传递给容器(不是上一示例的一部分)./p>
When I run this code in visual studio 2015, the code works correctly.But the code generates the following error in codeblocks : Segmentation fault(core dumped). I also ran the code in ubuntu with same error.
#include <iostream>
#include <immintrin.h>
struct INFO
{
unsigned int id = 0;
__m256i temp[8];
};
int main()
{
std::cout<<"Start AVX..."<<std::endl;
int _size = 100;
INFO *info = new INFO[_size];
for (int i = 0; i<_size; i++)
{
for (int k = 0; k < 8; k++)
{
info[i].temp[k] = _mm256_setr_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31);
}
}
std::cout<<"End AVX."<<std::endl;
return 0;
}
The problem is that prior to C++17 new
and delete
did not respect the alignment of the to-be-allocated type. If you look at the generated assembly from this simple function:
INFO* new_test() {
int _size = 100;
INFO *info = new INFO[_size];
return info;
}
You'll see that when compiled with anything prior to C++17 operator new[](unsigned long)
is called, whereas for C++17 a call is made to operator new[](unsigned long, std::align_val_t)
(and 32
is passed for the second parameter).
Play around with it at godbolt.
If you can't use C++17, you can overwrite operator new[]
(and operator delete[]
-- and you should overwrite operator new
and operator delete
as well ...):
struct INFO {
unsigned int id = 0;
__m256i temp[8];
void* operator new[](size_t size) {
// part of C11:
return aligned_alloc(alignof(INFO), size);
}
void operator delete[](void* addr) {
free(addr); // aligned_alloc is compatible with free
}
};
This is part of the previous godbolt example, if you compile with -DOVERWRITE_OPERATOR_NEW
.
Note that this does not solve the alignment issue when using std::vector
(or any other std
-container), for that you need to pass an aligned allocator to the container (not part of the previous example).
这篇关于在分配了new []的阵列上使用avx时出现分段错误(核心转储)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!