cwindowscrt

How to get rid of ucrt under Windows platform completely?


I'm currently writing a simple C runtime under Windows platform to learn better how the compiler/linker works.

The demo project is here: MarsCRT

I'm currently working on strlen(). This function looks like this:

// file: MarsString.c
size_t strlen(char* Char)
{
    size_t Length = 0;
    for(;Char[Length]; Length ++);
    return Length;
}

But when I compile the project

cl /c /GS- ./src/MarsEntry.c ./src/MarsIO.c ./src/MarsMalloc.c ./src/MarsPrintf.c ./src/MarsString.c
...plenty of warnings...
C:\Users\z\Project\Github\dev\marscrt\src\MarsCRT.h(41): error C2371: 'strlen': redefinition; different basic types
C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\ucrt\string.h(215): note: see declaration of 'strlen'
...

It seems that I didn't get rid of the default ucrt correctly. I check the cl.exe /help but did not find the answer I expected. So I wonder how to compile the project without ucrt?

I have tried adding /X in the cl.exe as flag, but the project cannot even find <Windows.h>. I also tried the /MD and /MT compiler flags but none of them work as I expected.

Actually I can just add the prefix like mars_strlen() to bypass the ucrt redefinition, but that's not what I want.


Solution

  • Per the (draft) C11 standard, strlen() is a reserved identifier:

    7.1.3 Reserved identifiers

    1. Each header declares or defines all identifiers listed in its associated subclause, and optionally declares or defines identifiers listed in its associated future library directions subclause and identifiers which are always reserved either for any use or for use as file scope identifiers.

    . . .

    1. No other identifiers are reserved. If the program declares or defines an identifier in a context in which it is reserved (other than as allowed by 7.1.4), or defines a reserved identifier as a macro name, the behavior is undefined.

    Note that the strlen() identifier is "always reserved". Creating an identifier such as strlen() in your code, per the C standard, "always" invokes undefined behavior. The behavior is undefined whether or not specific header files that define strlen() are included, and the behavior is undefined whether or not specific libraries are linked.

    You may be able to work around issues and make your code work, but you can never really know that it will work in the future under different conditions. That's what "undefined behavior" means - you can never know.