【问题标题】:SEGFAULT in -O3 mode?-O3 模式下的 SEGFAULT?
【发布时间】:2016-02-23 22:19:32
【问题描述】:

我将我的问题总结为以下短程序。

它仅在 -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;
}

请告诉我,我做错了什么?

【问题讨论】:

  • 这严重违反了the strict aliasing rule。至于崩溃,可能是因为您访问了未对齐的数据。由于别名问题,它可能无济于事,但尝试编译更多警告(例如-Wall -Wextra -pedantic),看看它是否告诉你什么。
  • @JoachimPileborg 我在 MSVC 上用 -W4 -Wx 编译了这段代码,它编译得很好。
  • AFAIK MSVC++ 从不假设严格的别名规则,并且不会根据这些规则进行任何优化。
  • @AlgirdasPreidžius I compiled it with clang 它确实抱怨 "cast from 'char *' to 'float *' 将所需的对齐方式从 1 增加到 4"。跨度>
  • 这就是当你从事黑客行为时会发生的事情。

标签: c++ gcc optimization segmentation-fault


【解决方案1】:

SEGFAULT 的来源不仅仅违反了严格的别名规则,因为即使使用 -fno-strict-aliasing 标志,问题仍然存在。

确实是在访问未对齐的内存,但不是那么简单。作为现代处理器,通常允许未对齐的内存访问,现在甚至没有太多的开销。我已经进行了一些基准测试,但在我的 Intel(R) Xeon(R) CPU E5-2680 v2 @ 2.80GHz 上没有观察到 algined 读取与未对齐读取的巨大差异。网络上也有 some 非常相似(或多或少)的结果。

我的问题是-O3 模式启用了-ftree-vectorize 标志,因此我的for 循环被矢量化(正如我使用-ftree-vectorizer-verbose 标志所看到的那样)。并且 (AFAIU) 不支持(还没有?)使用 矢量化 指令进行未对齐的内存访问,因此存在运行时异常。

This article 在理解理论方面帮助了我很多,尽管今天未对齐的内存访问似乎不像以前那么有害,尽管仍然很棘手

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-02-25
    • 1970-01-01
    • 2011-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-08
    • 2011-03-09
    相关资源
    最近更新 更多