【问题标题】:BadImageFormatException when using IEnumerable and Multi Inheritance使用 IEnumerable 和多继承时出现 BadImageFormatException
【发布时间】:2012-08-10 19:04:48
【问题描述】:

今天我遇到了一个非常奇怪的问题,我能够解决,但我仍然不明白为什么会这样。这是场景:

编辑

我将场景更改为更简单: 我有一个执行代码的程序和 2 个 Importers,一个具有泛型类型的基类和另一个仅调用基方法并对其进行迭代的类 (ImplementingImporter)。 这是完整的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace IEnumeratorLoadProblem {
    class Program {
        static void Main(string[] args) {

            var importer = new ImplementingImporter();
            try {
                var data = importer.GetData().ToArray();
            } catch (BadImageFormatException ex) {                
                Console.WriteLine("Why does this fail? " + ex.ToString());
            }

            Console.WriteLine("Press enter to quit");
            Console.ReadLine();
        }
    }

    class BaseClassImporter<T> {

        public virtual IEnumerable<T> GetData() {
            yield break;
        }
    }

    class ImplementingImporter : BaseClassImporter<int> {
        public override IEnumerable<int> GetData() {
            // iterating seems to cause the problem
            foreach(var dataByBaseImpl in base.GetData()) {
                yield return dataByBaseImpl;
            }
        }
    }
}

我收到以下错误:

System.BadImageFormatException:尝试加载程序 格式不正确。 (HRESULT 异常:0x8007000B)

当我将代码从使用的导入器更改为它时有效

class ImplementingImporter : BaseClassImporter<int> {
    protected override IEnumerable<int> GetData() {
        return base.GetData();
    }
}

不幸的是,我无法查看生成的 IL 代码,因为 ILSpy 和 Reflector.NET(版本 6)都显示了一个内部错误(我认为这是一个 ArgumentOutOfRangeException)。因为害怕使用ildasm,所以没有尝试直接看IL Code。

我猜这与生成的 IL 代码有关,但我想不出导致问题的场景。

有什么想法吗? 如果场景不够清晰,请发表评论,我会尽力使其更清晰。

编辑:

使用的 .NET 版本:4.0。该应用程序是使用 VS 2010 SP1 的 ConsoleApplication。 构建平台目标是 AnyCPu,但使用 x86 时也会出现问题。 我的机器有一个 64 位系统(Windows 7)。 使用 .NET 4.0 客户端配置文件时也会发生异常。

该示例是单个项目,没有使用外部/非托管库,因此不应出现建议的问题(例如,在运行 64 位时引用 32 位程序集)。

【问题讨论】:

  • 此异常通常是当您处于 32/64 位进程中尝试加载其他“位”的 DLL 时。一个进程只能针对一个平台,并且一旦选择,只能加载同一平台的 DLL(一次 32 位,始终为 32 位 - 与 64 位相同)。确保您正在构建的 DLL 上的目标平台都是相同的,无论是 x86/x64 显式(但都相同)还是 AnyCPU 用于隐式选择位数。
  • 这也是我的第一个猜测,所以我检查了选项并创建了一个项目来重现问题(我想当所有内容都在一个程序集中时,它不应该是构建问题)。我将在问题中添加一些关于使用的 .NET 版本等的其他信息
  • 同样的规则适用于也在进程内运行的其他第三方托管和非托管 DLL。
  • 该解决方案仅包含单个项目,不包含外部 dll。应该可以将给定的场景复制到一个文件中并运行它。也许我可以简化场景。
  • 我更新了示例以重现问题。

标签: c# generics yield il


【解决方案1】:

确保您的所有项目都使用相同的编译选项(AnyCPU、x86 或 x64)。

如果您使用任何外部 dll,请确保它们兼容(即 x86 机器上为 32 位,x64 机器上为 64 位)。

如果您想在 x64 机器上使用 32 位 dll,那么您需要将主 .exe 设置为编译为“x86”而不是“任何 CPU”——这将强制整个应用程序以 32 64 位 PC 上的位进程。 (如果您不这样做,您的 exe 将在 x64 机器上被 JIT 编译为 64 位应用程序,然后尝试调用您的 32 位 dll,这将抛出您得到的异常)

【讨论】:

  • 该解决方案仅包含单个项目,不包含外部 dll。应该可以将给定的场景复制到一个文件中并运行它。也许我可以简化场景...
【解决方案2】:

这似乎是yield return 语句的错误:

https://connect.microsoft.com/VisualStudio/feedback/details/677532/an-attempt-was-made-to-load-a-program-with-an-incorrect-format-exception-from-hresult-0x8007000b#details

他们声明它已在 VS2012(或“VS 2010 之后的版本”)中修复。

我正在使用 VS2010 SP1 运行针对 .NET Framework 4 的控制台应用程序,并且可以确认我遇到了与您相同的错误。我没有安装 VS2012 可以试用。

这里提出了一个类似的问题:

Iterator blocks and inheritance

另一个可疑的类似示例(这次是异步,但再次在MoveNext 上触发):

C#5 AsyncCtp BadImageFormatException

其他资源:

【讨论】:

  • 感谢您的链接。我仍然可以使用来自 connect.microsoft.com 的代码重现该错误。我猜微软对固定的解释与我不同。
  • @BernhardKircher 是的,我也可以复制它。
  • @BernhardKircher 发现了另一个奇怪的情况,这次是异步的,但仍然是生成的代码。
  • @BernhardKircher:他们说它已在 VS2010 之后的版本中修复,因此您可能需要尝试 VS2012 才能真正得到修复。
  • @JasonWilliams 我实际上并没有发现,我已经修改了我的答案。
猜你喜欢
  • 2015-05-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-19
  • 1970-01-01
  • 2019-05-27
相关资源
最近更新 更多