在没有CRT、memcpy和memset内置函数的情况下构建时出现连接错误

7

我试图构建一个尽可能小的应用程序,因此我尝试使用 Win API 调用而不是使用标准 C/C++ 调用来避免使用 CRT。很不幸,我仍然收到了一个链接器错误:

Error   2   error LNK2001: unresolved external symbol _memcpy

我在我的代码中没有调用memcpy,因此我认为其中一个Windows函数正在调用它。打开内置函数会出现未解决的符号_memset,但我也没有使用它。据我理解,启用内置函数应该包括memcpy和memset。
由于我的代码太长无法发布,以下是我的程序中的Win API调用:
- lstrcpy - wsprintf - CopyMemory - 如果我将其注释掉,则错误会切换到_memset - OpenFileMapping - MapViewOfFile - CreateFileMapping
我的问题:
- 如果我声明了/Oi,为什么内置函数没有被包含? - 我需要自己声明memset和memcpy吗?
- 如果是这样,如何在不引起Visual Studio重新定义内置函数的情况下进行声明?

2
代码优化器可以轻松地将 for(;;) 循环替换为 memcpy 或 memset 调用。您必须为它们提供实现。 - Hans Passant
我刚刚写了它们,它们可以工作:)。然而,如果我设置/Oi,我仍然很好奇为什么它们没有被包括在内置函数中。这是我第一次做这样的事情。也许你(或其他人)可以解释一下? - Knox
3
可能会有所帮助(或者至少在快速检查时看起来是这样)。请访问此网址:https://dev59.com/gnA85IYBdhLWcg3wHvo0 - WhozCraig
4个回答

7
/Oi没有被文档化为必须在所有内置函数中插入的选项,它只是给编译器提供了这样做的选择。我无法弄清楚MSVC使用什么逻辑来得出最终结论,但一些因素包括项目模式(在RELEASE中注入内置函数比DEBUG更有可能)和函数的长度。
最近的Visual Studio版本确实将MSVCRT依赖项整合到编译器中,越来越难以生成不依赖于标准C运行时的代码。
解决这些问题的标准方法(虽然被微软极度鄙视)是链接到系统副本的MSVCRT.dll,它以某种形式与所有版本的Windows一起发布。只要您使用标准C函数如memset,您可以安全地忽略Microsoft的不悦之眼,并链接到您想要的内容,但不要尝试使用由CRT提供的更复杂的函数和API。
要链接到msvcrt.dll,您需要使用LoadLibrary等方法或使用预生成的msvcrt.lib(Microsoft故意不提供)告诉MSVC哪些函数在系统MSCRT.dll中可用。
更新:我们现在发布了预先创建的mscvrt.lib文件,用于静态链接到x86和x64平台的CRT(自担风险!):https://github.com/neosmart/msvcrt.lib

对于mem和str函数,GCC似乎主要在大小为常量(在编译时已知)时使用'_builtin'进行优化。MSVC可能以类似的方式行事。 - duanev

1

memset()来自于ZeroMemory()

当遇到这个问题时,我只是在"The C Programming Language"中输入了memcpy、memmove和memset的规范定义。


-1

我遇到了类似的问题,将vcruntime.lib添加到链接器选项中,然后重新构建就解决了。


-5

你无法避免链接 CRT。但是,为了减小 EXE 文件的大小,你可以静态链接 CRT。链接器将剥离所有不必要的 CRT 代码,因此你的应用程序将尽可能地小。并且不会出现任何链接器错误。


6
我可以偶尔像我一样避免链接VC运行时库,无论是动态还是静态的。使用纯本地WIN32 API编写应用程序或动态链接库并不罕见,虽然不常见,但在某些情况下可能会更有优势。你不能得到一些重要的好处,但这确实是可能的。 - WhozCraig
WhozCraig是正确的。虽然这并不容易。如果你尝试这个,准备好解决链接器错误、性能问题和其他复杂的问题。我发现这个非常有帮助。链接 - walkingTarget

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