【问题标题】:Why does g++ optimize out a critical section of the following code?为什么 g++ 会优化以下代码的关键部分?
【发布时间】:2018-03-12 16:41:24
【问题描述】:

以下代码导致我的程序崩溃,因为

void fractalizeSegment() {
        // Assume next != NULL
        double deltaX = next->x - x;
        double deltaY = next->y - y;

        // Add 3 new points labeled a1, a2, a3 from this to next
        Point a3(x + 2.0*deltaX/3.0, y + 2.0*deltaY/3.0, next);
        double sqr3 = std::sqrt(3.0);
        Point a2(x + deltaX/2.0 - sqr3*deltaY/2.0,
             y + deltaY/2.0 + sqr3*deltaX/2.0,
             &a3);
        Point a1(x + deltaX/3.0, y + deltaY/3.0, &a2);

        next = &a1;
    }

以某种方式优化

void fractalizeSegment() {
    next = &a1;
}

在p0 = {x = 0, y = 0, next = 0x7ffffffffe100}上调用方法, 指向 p1 = {x = 1, y = 0, next = 0x0}。

通过在调试器中分析程序我发现当我在方法fractalizeSegment中时:

a1 = {x = 6.9533558075099091e-310, y = 6.9533558075098597e-310, next = 0x7fffffffe190}

地址a1.next有

a2 = {x = 6.9533558074508189e-310, y = 4.9406564584124654e-324, next = 0x34}.

试图遵循 (*a2.next).next 会导致分段错误。

为什么 g++ 会这样优化我的代码?如何预防?

我发现的当前解决方法是打印出 a1、a2 和 a3 的值, 这阻止了优化。

【问题讨论】:

  • 也许它确实假设next != NULL? GCC 在优化这样的代码时非常积极地利用未定义的行为。
  • next = &a1; 将立即悬空。
  • 在代码周围添加 if(next != NULL) 不会改变行为

标签: c++ g++ compiler-optimization


【解决方案1】:

a1 是一个局部自动变量,在从函数返回时将被销毁,因此此后对*next 的任何使用都将是未定义的。编译器认为您肯定不会使用这些值,所以为什么还要计算它们。

您可能想在堆中创建a1

next = new Point(x + deltaX/3.0, y + deltaY/3.0, &a2); //no need of a1.

也许a2a3 也应该动态分配,但这取决于Point 的实现,您没有显示。

记得delete某处分配的对象。

【讨论】:

  • “在堆中”?肯定是“在堆上”。
  • 你真的在争论“in”和“on”吗?后者比前者更惯用,后者更准确。
  • @tambre: 嗯,我不是母语人士,我对 inon 有困难... 快速搜索on google 显示 on 在该上下文中的使用量大约是 in 的两倍(在该上下文中?),但两者都经常使用。不过,我觉得意思还是很清楚的。
  • @StoryTeller 是的,它是针对 tambre,但你的分析恰恰相反:“in”和“on”确实是“former”和“latter”,因为“on”比更准确的“in”更惯用。我不同意 tambrerodrigo 在选择“in”而不是“on”方面遇到困难——工作和 rodrigo的用法没有错。
  • @Cheersandhth.-Alf:关于&a2 可能不正确,也可能不正确。这取决于Point 是否保留对该传递点的引用(作为链表)。如果是这样,那么&a3 也是错误的,它们都需要动态分配。如果该指针仅用作参考而不保留,那么一切都很好。
猜你喜欢
  • 2022-07-05
  • 2019-03-01
  • 2017-10-27
  • 1970-01-01
  • 2012-09-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-08
  • 1970-01-01
相关资源
最近更新 更多