Haskell 追查哈斯凯尔断层

Haskell 追查哈斯凯尔断层,haskell,Haskell,这真是太气人了\up>我所知道的唯一有用的方法是使用Debug.Trace import Debug.Trace 与 然后 main = (1 + 2) `debug` "adding or whatever and whatnot (also can have code here)" 您已经在记录您对不安全原语的使用 您是否编写了一个程序来查看这些日志中是否存在违反不变量的情况?将已知的不安全函数替换为它们的安全、检查过的版本。检查日志中会出现的异常,并修复代码。可能测试程序和带有库的程序

这真是太气人了\up>我所知道的唯一有用的方法是使用Debug.Trace

import Debug.Trace

然后

main = (1 + 2) `debug` "adding or whatever and whatnot (also can have code here)"

您已经在记录您对不安全原语的使用


您是否编写了一个程序来查看这些日志中是否存在违反不变量的情况?

将已知的不安全函数替换为它们的安全、检查过的版本。检查日志中会出现的异常,并修复代码。

可能测试程序和带有库的程序之间的区别在于,在后一种情况下,分配更多,因此调用GC的频率更高

读卡器线程看起来像的数组副本已被删除 不安全冻结,而写入程序线程继续并发运行 变异它


GC可能无法跟踪可变数组在冻结后是否仍被引用。在这种情况下,GC可能会移动冻结的数组,但writeArray会使用旧指针执行写入操作。

可能是固定的:

我改变了一些东西,代码不再崩溃。这可能只是一个侥幸,或者我可能“真的”解决了这个问题。很难说

假设:

问题似乎是从并发线程读取同一数组的可变和不可变副本。(即使简化测试正好做到这一点,并且不会崩溃。)

我让网络线程从一个无关的不可变数组读取,崩溃停止了。我甚至添加了一个循环,将数据从一个可变数组复制到另一个新的可变数组,然后新数组被冻结和检查。这似乎很有效

因此,这似乎只是GHC在处理对同一阵列的两个版本的并发访问时的一个小故障

(要么是这样,要么是侥幸。有几次我更改了程序中的某些内容,程序停止崩溃,然后又开始崩溃……)


更新:这似乎已完全修复。自从我做了这个改动之后,我再也没有发生过车祸了。感谢所有在这里帮助我的人。:-)

出于GC的目的,GHC以不同的方式对待可变和不可变指针数组。写入可变数组需要将对象放在可变列表上,并在卡表中设置一位。不可变数组两者都没有。因此,当您尝试写入已冻结的可变数组时,可以将新一代指针写入旧一代。在次要GC期间不扫描旧一代,因此当次要GC运行时,将收集该值。然后,因为数组指向垃圾,所以您可以选择segfault


解决方案:不要冻结阵列。如果必须,请使用
unsafePerformIO
进行读取。

是的,我的代码中已经充斥了
putStrLn
语句。(因为我在玩可变数组,所以不管怎样,它都在
IO
中运行。)从print语句中我可以看出,一切都很正常。然而。。。你试过在C阶段停止GHC并痛苦地查看输出吗?叮当声分析器可能会帮助您找到任何潜在的内存管理问题。我安装的版本肯定有它。哦,天哪,“邪恶的mangler”已经被删除,通过C注册的编译不再受支持。我必须有一个相当旧的版本。即使你不能(或不想)共享库,也许你可以共享测试代码?@gspr测试程序有点大。我怀疑是否有人会通读这一切来帮我解决问题。但是,如果有人认为它会有帮助,我当然可以发布它……您是否尝试过进行干净的构建……?如果您可以将代码放在某个地方(可编译,希望没有奇特的依赖项),我可以看一看。我喜欢寻找虫子:)好吧,也许不需要移动“冻结”阵列?未定义的行为不一定总是会崩溃。我有一种令人沮丧的感觉,你在分配问题上可能是对的。
main = (1 + 2) `debug` "adding or whatever and whatnot (also can have code here)"