【问题标题】:Compiler Bug when using ?. resulting in a Bad Image that fails PEVerify使用时的编译器错误?。导致 PEVerify 失败的错误图像
【发布时间】:2016-11-13 23:13:43
【问题描述】:

我偶然发现了一些奇怪的东西:我得到了一个BadImageFormatException,但不知道它可能指的是什么图像(程序集)。

我简化了解决方案,使其仅包含一个没有依赖关系的项目:

如你所见,它只使用System(和mscorlib),当然我不会在运行时加载程序集。

它使用 .NET 4.5.2 编译为 AnyCpu,使用 C#6 编译为 VS 2015,尽管这些都不重要。

我尝试使用 C#5 制作示例,但是一旦我替换了所有“?”。运营商,它停止发生。

我已经主持了这个项目,以便人们可以自己尝试:

git clone -b crash-sample https://github.com/jtheisen/moldinium.git

我在 4 台机器上进行了干净构建和测试,都显示了相同的效果。

崩溃的堆栈跟踪是:

Ex.: System.BadImageFormatException: An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)
   at IronStone.Moldinium.LiveList.<>c__DisplayClass10_0`1.<Where>b__2(ListEvent`1 v)
   at IronStone.Moldinium.ActionObserver`1.OnNext(T value) in C:\Source\Repos\moldinium\ConsoleApplication1\Rx.cs:line 51
...snipped...

在输出上运行 PEVerify 会产生以下错误:

[IL]:错误: [C:\Source\Repos\moldinium\ConsoleApplication1\bin\Debug\Bad.exe : IronStone.Moldinium.LiveList+c__DisplayClass10_0`1[TSource]::b__2][offset 0x0000013B] 无法解析令牌。

从 Select.cs 文件中删除所有 ?. 运算符可解决此问题。

使用 ILSpy 我已将问题隔离到:

IronStone.Moldinium.LiveList.<>c__DisplayClass10_0`1.<Where>b__2

您可以在 gist here 中查看该方法的 IL 转储(通过 ILSpy)。 Bad IL 是使用?. 时,Good IL 是 C# 5.0 样式。

这是使用 VS2015.3 构建的

CSC 版本:Microsoft (R) Visual C# 编译器版本 1.3.1.60616

【问题讨论】:

  • @DaveShaw 看来我很幸运能找到你。我在这里超出了我的深度。
  • 我已经重写了这个问题并合并了我的 cmets,以便更多地关注编译器错误,而不是运行时崩溃。
  • 你可能想在github.com/dotnet/roslyn/issues上发帖
  • @ScottChamberlain - 我想知道是否有人会缩小范围,但我还是发布了一个问题:github.com/dotnet/roslyn/issues/12439

标签: c# visual-studio-2015 roslyn c#-6.0


【解决方案1】:

我帮不了你,因为这确实是一个错误。但是我可以带你到 bug 发生的地方,它可以帮助你在几行代码中重现 bug。

namespace ElvisBugInNullableGenericStructWithNestedTypeParameter
{
    struct MyGenericStruct<T> { }
    class Program
    {
        static void Main() { }

        void Test<T>()
        {
            Func<T, bool> func = (arg =>
                {
                    MyGenericStruct<T>? v1 = null;
                    return v1?.ToString() == null;
                });
        }
    }
}

如果我将 MyGenericStruct&lt;T&gt;? 替换为 MyGenericStruct&lt;int&gt;? 它将起作用。

问题是,由于某种原因,当我们在可空结构中使用外部T,然后我们尝试使用猫王运算符? 时,类型未知(无法解析令牌)。

更新 如果你想解决你的问题,你不需要删除所有的 Elvis 运算符,只需将它们从 public static ILiveList&lt;TSource&gt; Where&lt;TSource&gt;(this ILiveList&lt;TSource&gt; source, Func&lt;TSource, Boolean&gt; predicate) 方法中的 Subscribe 操作中删除即可。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-08
    • 1970-01-01
    • 2015-09-13
    • 1970-01-01
    • 2010-11-07
    • 2017-03-14
    相关资源
    最近更新 更多