Question

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?
Was it helpful?

Solution

/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

OTHER TIPS

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".

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

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top