Linking error when building without CRT, memcpy and memset intrinsic functions
Asked Answered
B

4

8

I'm trying to build an application as tiny as possible, and in doing so I'm trying to avoid use of the CRT by using Win API calls instead of standard C/C++ calls. Unfortunately, I'm still getting a single linker error:

Error   2   error LNK2001: unresolved external symbol _memcpy

I don't call memcpy anywhere in my code, so I presume one of the Windows functions is calling it. Turning on intrinsic functions gives an unresolved symbol _memset, which I don't use either. From my understanding, both memcpy and memset should be included with intrinsic functions enabled. Since my code is too long to post, here are the Win API calls in my program:

  • lstrcpy
  • wsprintf
  • CopyMemory - the error switches to _memset when I comment this out
  • OpenFileMapping
  • MapViewOfFile
  • CreateFileMapping

My questions:

  • Why aren't the intrinsic functions being included if I have /Oi declared?
  • Do I need to declare memset and memcpy on my own?
    • If so, how do I do so without Visual Studio complaining of redefinition of intrinsic functions?
Brotherly answered 27/1, 2014 at 3:26 Comment(3)
The code optimizer readily replaces for(;;) loops by memcpy or memset calls. You must provide an implementation for them.Jurkoic
I just wrote them and it worked :). However, I'm still curious as to why they aren't included as intrinsic functions if I set /Oi. This is my first time doing anything like this. Perhaps you (or someone else) could explain?Brotherly
This might help out (or at least it looks so at a brief review).Parboil
A
1

memset() is coming from ZeroMemory()

On hitting this I just typed in the canonical definitions of memcpy, memmove, memset out of "The C Programming Language".

Apologetic answered 7/11, 2017 at 4:36 Comment(0)
F
7

/Oi is not documented as necessarily inserting all intrinsics where possible, instead it merely gives the compiler the option of doing so. I haven't been able to figure out what logic MSVC uses to reach its final conclusion, but some factors include the project mode (it's far more likely to inject the intrinsics in RELEASE as compared to DEBUG) and the length of your functions.

Recent versions of Visual Studio really have integrated MSVCRT dependencies into the compiler and it's become increasingly harder to generate code that does not depend on the standard C runtime.

The standard way of working around these issues (though extremely looked down upon by Microsoft) is to link against the system copy of MSVCRT.dll, which ships in some form or the other with all versions of Windows. So long as you are using standard C functions like memset you can soundly ignore Microsoft's piercing glares of disapproval and link away to your heart's content, but don't try to use it for more complicated functions and APIs provided by the CRT.

To link against msvcrt.dll you'll need to either use LoadLibrary and co or else use a pre-generated msvcrt.lib (Microsoft purposely does not provide one) to tell MSVC which functions are available in the system MSCRT.dll


Update: we now publish precreated mscvrt.lib files for statically linking against the CRT (at your own risk!) for x86 and x64 platforms: https://github.com/neosmart/msvcrt.lib

Fetterlock answered 13/10, 2017 at 0:24 Comment(1)
For the mem* and str* functions, GCC appears to optimize with '_builtin' mostly when the size is constant (known at compile time). MSVC likely behaves in a similar manner.Metzger
A
1

memset() is coming from ZeroMemory()

On hitting this I just typed in the canonical definitions of memcpy, memmove, memset out of "The C Programming Language".

Apologetic answered 7/11, 2017 at 4:36 Comment(0)
A
-1

I faced similar issue, adding vcruntime.lib to the Linker options and then rebuild helped me.

Azal answered 8/3, 2022 at 4:36 Comment(0)
O
-6

You cannot avoid linking to CRT. However, to reduce the size of your EXE, you can link to CRT statically. The linker will strip out all the unneeded CRT code, so your application will be as small as possible. And there won't be any linker errors.

Obstetrics answered 27/1, 2014 at 3:31 Comment(2)
You can avoid linking to the VC-runtime, both dynamically and statically, as I have done so on occasion. Native WIN32API-only applications or DLLs are not unheard of, and though rare there are times when they are advantageous. There are some significant benefits you don't get, but it is possible.Parboil
WhozCraig is right. It isn't easy though. If you attempt this, be ready to tackle linker errors, performance problems, and other complications. I found this very helpful.Threesquare

© 2022 - 2024 — McMap. All rights reserved.