在没有C-runtime和VS2010的情况下链接时未解析的符号

时间:2011-09-14 18:08:22

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

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

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

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

_ftol2_sse:将float转换为long。尽管关闭了SSE代码生成,我仍然得到了这个。

_CIpow:另一个战俘功能。我想知道为什么编译器会生成这个而不是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
    }
}

2 个答案:

答案 0 :(得分:3)

这是我必须从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建立极简主义程序的地方,在那里我找到了一些这样的信息;如果您仍有问题,可能会有其他提示。

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

答案 1 :(得分:2)

我还参与了一个用Visual Studio(.NET 2003)编译而不需要CRT的项目。更新版本的VS更难以使用,我们发现不值得让黑客使用它。

相反,您可能需要查看minicrt/lictiny。谷歌在奥马哈使用它 - 这是Chrome和谷歌地球的自动更新程序。

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