【发布时间】:2018-10-30 08:15:57
【问题描述】:
我在 C# 的托管代码中遇到了访问冲突异常和致命的执行引擎错误(似乎是相同的错误)。我已将其范围缩小到以下 sn-p。我错过了什么吗?我认为托管代码中不应出现此类异常。我在 .net 4.7 和 4.5 以及多台不同的计算机上都看到过它? 这是 .Net 中的一个已知问题吗?
public static class FatalExecutionEngineBugExposer
{
public static void Main(string[] args)
{
for (int i = 0; i < 500000; i++)
{
try
{
var testProblem = new TestProblem();
testProblem.AddTrianglesExperiment();
}
catch (Exception e)
{
Console.WriteLine(e.GetBaseException());
}
}
}
public class TestProblem
{
public struct Point
{
public double X, Y, Z;
}
public void AddTrianglesExperiment()
{
var points = new Point[28800];
Parallel.ForEach(Partitioner.Create(0, points.Length),
range =>
{
// Create cache
var cache = new CubeRefCache();
cache.Entries = new CubeRefCacheEntry[20000];
// Add triangles
for (int i = range.Item1; i < range.Item2; i++)
{
ProcessTriangle(ref points[i].X, ref points[i].Y, ref points[i].Z, cache);
}
});
}
void ProcessTriangle(ref double pt1, ref double pt2, ref double pt3, CubeRefCache cache)
{
cache.Add(0, 0);
}
public struct CubeRefCacheEntry
{
public int Index;
public int Item;
}
class CubeRefCache
{
internal CubeRefCacheEntry[] Entries;
internal void Add(int index, int item)
{
Entries[0].Index = index;
Entries[0].Item = item;
}
}
}
}
这个 sn-p“通常”在一分钟内失败。
更新:它可能应该以 64 位运行。如果使用“Any CPU”编译,则重现问题需要更长的时间。
UPDATE2:我的用途:
【问题讨论】:
-
您的 ProcessTriangle 每次都访问相同的条目是有意的。请为分区器添加代码
-
"Partitioner" 是 .NET 框架的一部分,无需为此添加代码。
-
如果此代码因致命的执行引擎异常而失败,那么在我看来,这就像 .NET 运行时中的某个错误。当然,代码是人为的,就像缓存从不添加任何东西,只是将所有内容存储在第一个元素中,但如果它重现崩溃,那就足够了。但是,我已经在 LINQPad 中运行了这段代码至少 5 分钟,它还没有崩溃,所以我想如果它在一分钟内可靠地崩溃,那么肯定还有其他事情发生。
-
这是一个人为的例子并不重要。然而,当涉及到真正发现真正的问题(在运行时)时,可能会有一些不必要的部分和红鲱鱼,但这些都不重要。如果它是运行时中的错误,并且在我看来是这样(假设它确实崩溃,正如我所说的我无法重现它),那么它应该被修复或至少被放在优先级的错误列表中。 请不要抱怨所有使该代码有用或优雅的代码已被删除,这就是minimal reproducible example 的意思!
-
可以在 x64 上以 1 分 40 秒的速度进行复制。事实上,如果我将
public int Item;和Entries[0].Item = item;注释掉,它会立即或在几秒钟内崩溃。
标签: c# access-violation executionengineexception