我将我的问题总结为以下短程序。
它仅在 -O3 模式下导致 SEGFAULT(-O2 工作正常)。
根据 gdb
,它发生在 *f = 0
行。
#include <iostream>
void func1(int s, int t)
{
char* buffer = new char[s + t*sizeof(float)];
if (!buffer)
{
std::cout << "new failed\n";
return;
}
float* f = (float*)(buffer + s);
for (int i = 0; i < t; ++i)
{
*f = 0;
//std::cout << i << std::endl; // if uncomment this line everything will work fine
++f;
}
delete [] buffer;
std::cout << "done\n";
}
int main()
{
int s = 31, t = 12423138;
std::cout << s << " " << t << std::endl;
func1(s, t);
return 0;
}
请告诉我,我做错了什么?
最佳答案
SEGFAULT 的来源不仅仅违反了严格的别名规则,因为即使使用 -fno-strict-aliasing 标志,问题仍然存在。
确实是在访问未对齐的内存,但并没有这么简单。作为现代处理器,通常允许未对齐的内存访问,现在甚至没有太多开销。我已经完成了一些基准测试,并没有观察到我的 Intel(R) Xeon(R) CPU E5-2680 v2 @ 2.80GHz 上的对齐读取与未对齐读取有很大差异。还有some网络中的结果非常相似(或多或少最近)。
我的问题是 -O3
模式启用了 -ftree-vectorize
标志,因此我的 for
循环被矢量化了(正如我看到的使用-ftree-vectorizer-verbose
标志)。并且(AFAIU)不支持(还?)使用向量化指令进行未对齐的内存访问,因此出现运行时异常。
This article在理解理论方面帮助了我很多,尽管今天未对齐的内存访问似乎不像以前那样有害,但仍然很棘手
关于c++ - -O3 模式下的段错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33843444/