2

我正在实现一个带有指向一些手动管理内存的指针的结构。这一切都适用于 DMD,但是当我使用 GDC 对其进行测试时,它会因opEquals运算符重载而失败。我已将其范围缩小到 memcmp。在opEquals我将指向内存与 memcmp 进行比较时,它在 DMD 中的行为与我预期的一样,但在 GDC 中失败。

如果我返回并opEquals通过使用内置类型一次比较存储在手动管理内存 1 中的每个值来编写该方法==,则它在两个编译器中都有效。我更喜欢 memcmp 路线,因为它写起来更短,而且看起来应该更快(更少的间接、迭代等)。

为什么?这是一个错误吗?

(我使用 C 的经验是 10 年前,从那以后一直在使用 python/java,我在 C 中从未遇到过这种问题,但我并没有用那么多。)

编辑:

我正在比较的内存代表一个“真实”值的二维数组,我只是希望它被分配在一个块中,所以我不必处理锯齿状数组。我将在紧密循环中大量使用这些结构。基本上,我正在滚动我自己的矩阵结构,它将(最终)缓存一些经常使用的值(跟踪、行列式),并为不需要复制它的转置提供备用只读视图。我计划使用大约 10x10 到大约 1000x1000 的矩阵(尽管并不总是正方形)。

我还计划实现一个版本,通过 GC 分配内存ubyte[]并分析这两个实现。

编辑2:

好的,我尝试了几件事。我也有一些parallel循环,我有一种预感,这可能是问题所在。所以我添加了一些版本语句来制作并行和非并行版本。为了让它与 GDC 一起工作,我不得不使用非并行版本并更改realdouble.

在 GDC 下编译的所有案例。但是单元测试失败了,并不总是在同一行上,而是在opEquals我使用realor时始终在通话中parallel。在 DMD 中,所有案例都编译并运行没有问题。

谢谢,

4

1 回答 1

2

real有一点奇怪的大小:它是 80 位数据,但是如果你检查 real.sizeof,你会发现它比这更大(至少在 Linux 上,我认为它在 Windows 上是 10 字节,我打赌你不会在那里看到这个错误)。原因是为了确保它在字边界上对齐 - 四个字节的倍数 - 以便处理器在数组中更有效地加载。

每个数据元素之间的字节称为填充,它们的内容并不总是定义的。我自己还没有证实这一点,但@jpf 对这个问题的评论和我的直觉一样,所以我现在把它作为答案发布。

D 中的is运算符与 相同memcmp(&data1, &data2, data.sizeof),所以@jpf 的评论和你的评论memcmp是一样的。它检查数据和填充,而 == 只检查数据(顺便说一下,它对浮动类型有点特殊,因为它也比较 NaN,所以确切的位模式对这些检查很重要;实际上,当我看到问题标题是它与 NaN 相关!但不是这样)

无论如何,显然 dmd 也初始化了填充字节,而 gdc 没有,将其保留为并不总是匹配的垃圾。

于 2015-01-06T04:07:31.283 回答