【问题标题】:Unresolved symbols when linking without C-runtime with VS2010在没有 C-runtime 的情况下与 VS2010 链接时未解析的符号
【发布时间】:2011-11-17 06:25:36
【问题描述】:

我正在处理一个有大小限制的项目,所以我不想链接到 Visual Studio 的 C 运行时。我使用静态运行时 (/MT) 和 /NODEFAULTLIB:LIBCMT 标志来执行此操作。通过检查 VS 附带的运行时源,我已经解决了大部分问题。但是,编译器仍然会生成一些未解析的外部符号:

_chkstk:生成检查大于 4k 的函数的堆栈。我可以关闭它或提供一个虚拟功能吗?

__libm_sse2_pow 和其他 SSE 调用:我可以通过关闭 SSE 代码生成来避免这些,但如果可能的话,我想拥有它们。这些符号似乎来自英特尔库(libmmd.lib?)。为什么这部分是 C 运行时的一部分?

_ftol2_sse: 将浮点数转换为长整数。尽管关闭了 SSE 代码生成,我仍然得到这个。

_CIpow: 另一个 pow 函数。我想知道为什么编译器会生成这个而不是 SEE 。

是否有控制此代码生成的任何设置、预处理器宏或编译指示?我也尝试过使用 Visual Studio 6.0 SP6 中的 msvcrt.lib,但我使用的一些函数不适用于 VS2010 编译器。

编辑:

_chkstk可以在相关函数前面加上#pragma check_stack(off)来关闭。可以在Visual Studio自带的CRT源码中找到。

_CIpow 有点强硬。它是使用特殊调用约定的 pow 的内在版本。我找不到关闭它的方法,所以我最终自己在汇编程序中重新实现了它。我在这里得到了一些灵​​感:How to: pow(real, real) in x86。我有一段时间没有做汇编了,这是我第一次在 x86 上做。我没有针对所有情况进行测试,所以不能保证!如果您有任何改进建议或发现错误,请告诉我。

void __cdecl _CIpow(void)
{
    // implementation of pow function as 2^(y*log2(x)). this is the 
    // intrinsic version so base and exponent are already on the fpu 
    // stack ST0 and ST1. the result is pushed to ST0.
    // note that earlier rounding for fist was set to truncate
    int temp;
    __asm {
        // values are repushed, cause fyl2x will overwrite them both
        fld     st(0)           // push ST0 to ST0
        fld     st(2)           // push ST2 (ex ST1) to ST0
        fyl2x                   // ST1 = ST1*log2(ST0), pop ST0
        fist    temp            // assumes truncate rouning
        fisub   temp            // S0 = S0 - temp
        f2xm1                   // ST0 = (2^ST0)-1
        fld1                    // push 1 to ST0
        faddp   st(1),st(0)     // ST1 = ST1 + ST0, pop ST0
        fild    temp            // push temp to ST0
        fxch                    // swap ST0 and ST1
        fscale                  // ST0 = inc exp of ST0 by ST1
        fxch                    // put reslut in ST1
        fstp    st(0)           // pop ST0
    }
}

【问题讨论】:

  • 您使用的是什么指令或功能?通过摆弄设置,我仍然可以使用 VS2010 构建一个“小”可执行文件。
  • @Luke:我不想重新分发 msvcrt100.dll。我可以通过链接系统的 msvcrt.dll(由于 tell() 函数失败而无法工作)或链接到静态 msvcrt.lib 来避免这种情况,这会将可执行文件大小增加高达 200 KB。上面的符号是由简单的 float 到 long casts 和 math.h 函数生成的。

标签: c windows visual-studio linker code-generation


【解决方案1】:

这是我必须从 VS2010 中的默认 Win32 项目更改的内容:

调试

  • C/C++ - 代码生成 - 基本运行时检查 = 默认
  • C/C++ - 代码生成 - 运行时库 = 多线程调试 (/MTd)
  • 链接器 - 输入 - 忽略特定默认库 = libcmtd.lib

发布

  • 常规 - 整体程序优化 = 无整体程序优化
  • C/C++ - 优化 - 整个程序优化 = 否
  • C/C++ - 代码生成 - 运行时库 = 多线程 (/MT)
  • 链接器 - 输入 - 忽略特定默认库 = libcmt.lib

不得不做更多的事情来处理浮点数:

  • C/C++ - 命令行 = /QIfist(也称为 SetFloatingPointRoundingToTruncate;参见下面的链接)
  • extern "C" int _fltused = 1; // 编译器定义的全局变量,用于加载一些浮点数据

我遇到了interesting blog post,关于使用 VS 构建极简程序,我在其中找到了一些信息;如果您仍有问题,可能会有其他提示。

通过所有这些调整,我能够编译和链接一个将浮点数转换为 long 并调用一些 pow() 函数的程序。发布版本只有 3.5 KB,其中包括嵌入式清单。

【讨论】:

    【解决方案2】:

    我还参与了一个使用 Visual Studio (.NET 2003) 编译且不需要 CRT 的项目。较新版本的 VS 更难使用,我们发现不值得通过 hack 来使其工作。

    相反,您可能想查看minicrt/lictiny。 Google 在 Omaha 中使用它 - Chrome 和 Google 地球的自动更新程序。

    您可能还想尝试MinGW 工具链,因为它可以链接到 MSVCRT.DLL,它是一个系统组件,不需要由您的应用程序分发。

    【讨论】:

      猜你喜欢
      • 2015-10-14
      • 2016-12-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多