构建不使用CRT函数的Visual C++应用程序仍然引用某些函数的问题

10

这是至少两个密切相关但不同的问题系列的一部分,我希望单独提问是否正确。

我试图让我的Visual C++ 2008应用程序在没有C运行时库的情况下工作。它是一个Win32 GUI应用程序,没有MFC或其他花哨的东西,只有纯Windows API。

因此,我将项目属性->配置->C/C++->高级->省略默认库名称设置为Yes(编译器标志/Zl),然后进行重建。假装我已经编写了一个适当的入口点函数,这是我另一个问题的主题。

我得到了两个链接器错误;它们可能是相关的。链接器抱怨foobar.obj中未解析的外部符号__fltused_memcpy。不用说,我在我的程序中都没有明确使用它们,但是我确实在foobar.cpp的某个地方使用了memcpy。(我本来会使用CopyMemory,但是结果证明它被#define为与memcpy相同...)

(我以为可以通过使用编译器内在功能来解决memcpy问题,例如#pragma intrinsic(memcpy),但这没有任何区别。)

如果我查看预处理器输出(在编译器命令行中添加/P),则在foobar.i中看不到对__fltused_memcpy的引用。

那么,我的问题是:这些链接器错误源自何处,以及如何解决它们?


啊...在将这个东西拆分成两部分的过程中可能不小心丢失了。重新添加好了,谢谢! - Thomas
2个回答

16

__fltused 表示您正在使用或至少声明了一些浮点数或双精度数。编译器注入此“无用”符号以导致从 crt 加载浮点支持 .obj。您可以通过简单地声明一个名称为该名称的符号来避免这种情况。

#ifdef __cplusplus
extern "C" {
#endif
int _fltused=0; // it should be a single underscore since the double one is the mangled name
#ifdef __cplusplus
}
#endif

关于_memcpy函数——memcpy是一个__cdecl函数,所有的__cdecl函数都会自动加上一个_作为它们命名修饰的一部分。因此当你说“__cdecl memcpy”时,编译器和链接器会寻找一个名为'_memcpy'的符号。即使显式请求使用内置函数,但如果构建设置具有反对内置函数的调试设置,仍然可以导入它们。因此,你迟早需要自己实现自己的memcpy函数及其相关函数。


谢谢您的快速回答!不幸的是,__fltused 技巧对我没有任何作用。我在 foobar.cpp 的顶部放置了 int __fltused = 0;;无论是静态还是非静态都没有区别。 - Thomas
此外,我相当确定我没有在任何地方使用浮点数或双精度变量。我的源代码树中不包含这些词语。 - Thomas
啊,抱歉。我忘记了 extern "C" 部分。 - Chris Becke
2
应该使用单下划线,因为双下划线是编译器重命名后的名称。 - paulm
作为答案中使用的链接说明符的更紧凑替代方案,您可以使用 <winnt.h> 中声明的 EXTERN_CEXTERN_C int _fltused = 0;。无需基于 __cplusplus 预处理器符号进行区分,因为 EXTERN_C 宏已经处理了这个问题。 - IInspectable

2

我建议设置编译器选项,例如“生成汇编清单”,针对 foobar.cpp 文件进行一次编译,并检查汇编代码。这样做可以帮助你确定这些符号的使用情况。


我并不是x86汇编大师。但如果我能弄清楚工具,明天我可能会尝试一下。 - Thomas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接