【问题标题】:Is there any class count limit in MFC project compiled with /CLR使用 /CLR 编译的 MFC 项目中是否有任何类计数限制
【发布时间】:2014-12-26 08:08:40
【问题描述】:

有陷入过于具体的问题的风险......

给定一个使用 /CLR 编译的 C++ MFC(混合,非抖动)项目,我已经定义了 200 个类。

当我向该项目添加新的 empty 类时,在调试模式下编译和执行时会出现错误。

发生“System.IO.FileLoadException”类型的未处理异常 在未知模块中。

附加信息:无法加载文件或程序集 'ProjectA, Version=0.0.0.0,Culture=neutral,PublicKeyToken=null' 或其之一 依赖关系。无法找到或加载类型。 (HRESULT 的例外情况: 0x80131522)

ProjectA 是 MFC 项目本身的名称。项目配置中没有对任何ProjectA 程序集的引用,也没有对另一个自定义程序集的引用。

本项目仅引用了一些.NET Framework程序集,以使项目中的一些自定义类可以使用CLR类。

那么,问题是……

  • 你知道MFC C++项目有没有类号限制吗?

编辑:

正如我在 cmets 中所说,在发布模式下,编译成功且没有错误。

另外,我清理、构建、清理、关闭 Visual Studio、重新启动计算机......问题仍然出现。 如果我保持 200 节课,就没有错误。当我转到201时,出现错误。

目前我正在尝试在一个新的默认 MFC 项目中重现,添加类直到达到 200 个,以确认存在真正的限制。

编辑 2:错误修复

太好了。 @MSX@frymode 告诉我如何避免他的 cmets 出错。

在 Visual Studio 开发环境中(source/source):

  1. 打开项目的“属性页”对话框。
  2. 单击 C/C++ 文件夹。
  3. 单击代码生成属性页。
  4. 修改启用字符串池 (/GF) 属性。

谢谢你们!

【问题讨论】:

  • 在release模式下会不会出现同样的问题?
  • 另外,您是否尝试过清理和重建?
  • 否,在发布模式下编译成功且没有错误。是的。我清理,构建,清理,关闭 Visual Studio,重新启动计算机......如果我保持 200 个类,则没有错误。当我转到201时,出现错误。
  • 奇怪...有人通过以下步骤解决了这个问题: 在 Visual Studio 开发环境中设置此编译器选项 1. 打开项目的“属性页”对话框。 2. 单击 C/C++ 文件夹。 3. 单击代码生成属性页面。 4. 修改启用字符串池 (/GF) 属性。在命令行属性页中设置 /Gf。这是link
  • 很高兴我们提供了帮助。我们无法将其发布为答案,因为该解决方案无法回答您关于班级人数限制的问题。您可以保留问题,因为有人可能会知道答案。

标签: debugging visual-studio-2013 mfc c++-cli clr


【解决方案1】:

This link 表明命名空间(不是项目)中可以拥有的类型数量没有限制。考虑到命名空间可以跨不同的程序集拆分,您至少在理论上可以拥有无​​限数量的类型。但是,this post 确认 .DLL 中的最大类数 是 16777215。可能,在达到这个数量的类之前,你的内存就会用完:)

仅供参考:不过,每个类的字段数似乎有一个limit

附: 这是您的问题的解决方案,取自this link

  1. 打开项目的“属性页”对话框。
  2. 单击 C/C++ 文件夹。
  3. 单击代码生成属性页。
  4. 修改启用字符串池属性。

【讨论】:

    【解决方案2】:

    /GF hack 是解决此问题的已知解决方法。然而,这不是一个正确的方法,您正在将创可贴放在流血过多的伤口上。修复问题而不是打补丁非常重要,这也会严重影响程序在运行时的运行方式。

    问题制造者是 <Module> 类,它是 C++/CLI 编译器生成的内部类。您可以使用 ildasm.exe 或一个好的反编译器来查看它。此类需要作为程序中非类成员的声明的主目录,在本机 C++ 中有效但不受 CLR 支持。这要求每个变量或函数声明都是类的成员。 C++/CLI 编译器通过将这样的声明移动到<Module> 类中来解决它。

    但是,类中的成员数量是有限制的,它们在 .NET 程序集的元数据中用元数据标记表示。其他表的索引。高字节标识表号,低字节为表中的索引。

    您超出了该限制。这很糟糕。

    /clr 编译选项的一个问题是它工作得很好。它能够将任何符合 C++03 的本机 C++ 代码编译为 MSIL。这样的代码将通过抖动即时编译为机器代码,就像正常的托管代码一样。然而,它不是可验证的代码,它根本不像托管代码,你可以很容易地用指针摸索来炸毁你的程序。最重要的是,它不是使用本机 C++ 后端优化的代码。只有抖动优化器可以改进该代码,它几乎无法完成本地 C++ 优化器可以完成的质量工作,因为它在执行该工作的时间上有一个硬性上限。

    使用反编译器查看一下<Module> 类的结果。起初这将是压倒性的,你知道你现在有一个大的。您可以通过花更多时间将代码分离为托管部分和本机部分来解决此问题。本地代码应该编译的地方没有 /clr 生效。它是针对每个源文件的设置,您甚至可以在受#pragma 管理的单个源代码文件中来回切换。最简单的隔离方法是将本机代码保存在自己的库或 DLL 中。

    【讨论】:

    • 太棒了!不知道详情。
    • 我会的。我知道将 CLR 类直接包含到 MFC Native 项目中的决定是一个糟糕的决定。谢谢你的回答。
    猜你喜欢
    • 2023-03-05
    • 1970-01-01
    • 2010-10-23
    • 1970-01-01
    • 2010-09-23
    • 1970-01-01
    • 2016-05-21
    • 1970-01-01
    • 2011-05-03
    相关资源
    最近更新 更多