“Swift compiler or framework bug?” 可以翻译为 “Swift编译器或框架的问题?”

huangapple go评论68阅读模式
英文:

Swift compiler or framework bug?

问题

以下是一个简单的代码,用于在2D多边形中插入额外的点。它永远不会终止(在Xcode 14.3、iOS 16.4.1(a)上)。问题在注释中有解释 —— 看起来在 polygon.insert 后,如果插入的索引等于 polygon.countpolygon.count 返回错误的值。这真的不能是编译器/框架的错误,我漏掉了什么?

//
//  ViewController.swift
//  CompilerBug?
//

import UIKit
import simd

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        var polygon = [SIMD3<Float>(1.345, 0.0, 0.002), SIMD3<Float>(1.181, 0.0, -0.171), SIMD3<Float>(1.185, 0.0, -0.206), SIMD3<Float>(1.141, 0.0, -0.255), SIMD3<Float>(1.121, 0.0, -0.257), SIMD3<Float>(0.848, 0.0, -0.636), SIMD3<Float>(0.777, 0.0, -0.604), SIMD3<Float>(0.692, 0.0, -0.532), SIMD3<Float>(0.677, 0.0, -0.5), SIMD3<Float>(0.6976719, 0.0, -0.46364594), SIMD3<Float>(0.903, 0.0, -0.188), SIMD3<Float>(1.1739755, 0.0, 0.12979852)]

        ViewController.addPoints(to: &polygon, every: 0.05)
    }

    static func addPoints(to polygon: inout [simd_float3], every d: Float) {
        let threshold = d * d
        var i = 0
        while i < polygon.count {
            let j = (i + 1) % polygon.count // "A"
            while polygon[i].distanceSquared2D(polygon[j]) > threshold {
                let new = simd_float3(x: (polygon[i].x + polygon[j].x) / 2.0,
                                      y: 0.0,
                                      z: (polygon[i].z + polygon[j].z) / 2.0)
                // 当i+1等于polygon.count时,在插入后,“A”处的polygon.count调用返回的是插入前的计数!
                polygon.insert(new, at: i + 1)
            }
            
            i += 1
        }
    }
}

extension simd_float3 {
    public func distanceSquared2D(_ b: simd_float3) -> Float {
        return (self.x - b.x) * (self.x - b.x) + (self.z - b.z) * (self.z - b.z)
    }
}
英文:

Below is some simple code to insert additional points into a 2D polygon. It never terminates (on Xcode 14.3, iOS 16.4.1(a)). The cause is explained in the comments — it appears that polygon.count returns the wrong value after polygon.insert when the insertion index equals polygon.count. This can't really be a compiler/framework bug surely, what am I missing?

//
//  ViewController.swift
//  CompilerBug?
//

import UIKit
import simd

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        var polygon =  [SIMD3&lt;Float&gt;(1.345, 0.0, 0.002),SIMD3&lt;Float&gt;(1.181, 0.0, -0.171),SIMD3&lt;Float&gt;(1.185, 0.0, -0.206),SIMD3&lt;Float&gt;(1.141, 0.0, -0.255),SIMD3&lt;Float&gt;(1.121, 0.0, -0.257),SIMD3&lt;Float&gt;(0.848, 0.0, -0.636),SIMD3&lt;Float&gt;(0.777, 0.0, -0.604),SIMD3&lt;Float&gt;(0.692, 0.0, -0.532),SIMD3&lt;Float&gt;(0.677, 0.0, -0.5),SIMD3&lt;Float&gt;(0.6976719, 0.0, -0.46364594),SIMD3&lt;Float&gt;(0.903, 0.0, -0.188),SIMD3&lt;Float&gt;(1.1739755, 0.0, 0.12979852)]
        
        ViewController.addPoints(to: &amp;polygon, every: 0.05)
    }

    static func addPoints(to polygon: inout [simd_float3], every d: Float) {
        let threshold = d * d
        var i = 0
        while i &lt; polygon.count {
            let j = (i + 1) % polygon.count // &quot;A&quot;
            while polygon[i].distanceSquared2D(polygon[j]) &gt; threshold {
                let new = simd_float3(x: (polygon[i].x + polygon[j].x) / 2.0,
                                      y: 0.0,
                                      z: (polygon[i].z + polygon[j].z) / 2.0)
                // when i+1 equals polygon.count, the subsequent call to polygon.count at &quot;A&quot;
                // after insertion returns the count prior to the insertion!
                polygon.insert(new, at: i + 1)
            }
            
            i += 1
        }
    }
}

extension simd_float3
{
    public func distanceSquared2D(_ b: simd_float3) -&gt; Float {
        return (self.x - b.x) * (self.x - b.x) + (self.z - b.z) * (self.z - b.z)
    }
}

答案1

得分: 1

Here is the translation of the code part you provided:

"不清楚您认为代码应该执行什么操作,但如果您使用 print 语句进行仪器测量,您将看到它是以逻辑和一致的方式运行的:

while i < polygon.count {
    print(i, polygon.count)
    let j = (i + 1) % polygon.count
    while polygon[i].distanceSquared2D(polygon[j]) > threshold {
        let new = simd_float3(x: (polygon[i].x + polygon[j].x) / 2.0,
                              y: 0.0,
                              z: (polygon[i].z + polygon[j].z) / 2.0)
        print("insert")
        polygon.insert(new, at: i + 1)
    }
    i += 1
}

每当第一个 print 语句打印时,我们看到 &quot;insert&quot; 被打印的次数和 polygon.count 的增加总是相同的。因此,一个 insert 就是一个增加的 polygon.count,这是预期的(我假设也是期望的)。

然后当我们达到 i 为60和 polygon.count 为61时,内部的 while 循环会一直运行(我们会不断看到 &quot;insert&quot; 的输出,而不再返回到第一个 print),从而导致应用程序挂起。

因此,我看到的唯一错误,如果这不是您期望的结果,那就是您的程序本身。我猜想问题可能出在条件

polygon[i].distanceSquared2D(polygon[j]) > threshold

因为 ij 都没有改变,插入操作现在是在 j 的位置进行的。"

英文:

Unclear what you think your code is supposed to do, but if you instrument it with print statements you will see it is behaving logically and consistently:

    while i &lt; polygon.count {
        print(i, polygon.count)
        let j = (i + 1) % polygon.count
        while polygon[i].distanceSquared2D(polygon[j]) &gt; threshold {
            let new = simd_float3(x: (polygon[i].x + polygon[j].x) / 2.0,
                                  y: 0.0,
                                  z: (polygon[i].z + polygon[j].z) / 2.0)
            print(&quot;insert&quot;)
            polygon.insert(new, at: i + 1)
        }
        i += 1
    }

Every time the first print statement prints, we see that the number of times &quot;insert&quot; was printed and the increase in polygon.count are always the same. So one insert is one increment in polygon.count, which is as expected (and, I presume, desired).

Then when we reach i at 60 and polygon.count at 61, the inner while loop runs forever (we get a steady stream of &quot;insert&quot; without every coming round to the first print again) and so the app hangs.

So the only bug I see, if that's not the outcome you expect, is in your program itself. I suppose that the problem is that the condition

polygon[i].distanceSquared2D(polygon[j]) &gt; threshold

just runs away with you, because neither i nor j changes and the insertions are now taking place at the j position.

huangapple
  • 本文由 发表于 2023年5月13日 23:49:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/76243636.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定