visual-c++linkerstatic-linkingdumpbinstrncmp

Where is strnicmp on Windows?


I'm trying to compile Python on Windows in an unusual context, and running into this problem:

a.o : error LNK2019: unresolved external symbol strnicmp referenced in function connection_clear

Okay, so I'm not linking in the proper library containing strnicmp, which one is that? Couldn't find it, so I wrote a script to search through every .lib file on my entire hard disk, run dumpbin /exports on all of them, and collect the results.

And the result was that as far as this process could tell, there is no library containing strnicmp.

A bit more searching led me to https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/strnicmp-wcsnicmp?view=msvc-170

The Microsoft-specific function names strnicmp and wcsnicmp are deprecated aliases for the _strnicmp and _wcsnicmp functions.

On the face of it, that would seem to be the beginning of an explanation. Neither the linker nor I nor my search script can find strnicmp because at the object code level, it doesn't exist; it's probably just a #define in some header file, though that raises the question of why this was not working on the source file containing connection_clear.

Just to make sure, I wrote a test program.

(c1) R:\>type call-strnicmp.c
#include <stdio.h>
#include <string.h>

int main(int argc, char** argv) {
        if (argc == 2 && !strnicmp(argv[1], "foo", 3)) puts("you said foo");
        else
                puts("you did not say foo");
        return 0;
}

(c1) R:\>cl call-strnicmp.c
Microsoft (R) C/C++ Optimizing Compiler Version 19.31.31104 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

call-strnicmp.c
Microsoft (R) Incremental Linker Version 14.31.31104.0
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:call-strnicmp.exe
call-strnicmp.obj

(c1) R:\>call-strnicmp.exe foo
you said foo

Okay, so strnicmp is being called correctly, presumably via the aforementioned header. Just to make doubly sure:

(c1) R:\>dumpbin /symbols call-strnicmp.obj
Microsoft (R) COFF/PE Dumper Version 14.31.31104.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file call-strnicmp.obj

File Type: COFF OBJECT

COFF SYMBOL TABLE
000 01047980 ABS    notype       Static       | @comp.id
001 80010190 ABS    notype       Static       | @feat.00
002 00000002 ABS    notype       Static       | @vol.md
003 00000000 SECT1  notype       Static       | .drectve
    Section length   2F, #relocs    0, #linenums    0, checksum        0
005 00000000 SECT2  notype       Static       | .debug$S
    Section length   68, #relocs    0, #linenums    0, checksum        0
007 00000000 SECT3  notype       Static       | .text$mn
    Section length   5D, #relocs    6, #linenums    0, checksum D202F0CD
009 00000000 UNDEF  notype ()    External     | puts
00A 00000000 UNDEF  notype ()    External     | strnicmp
00B 00000000 SECT3  notype ()    External     | main
00C 00000000 SECT3  notype       Label        | $LN5
00D 00000000 SECT4  notype       Static       | .xdata
    Section length    8, #relocs    0, #linenums    0, checksum E7553388
00F 00000000 SECT4  notype       Static       | $unwind$main
010 00000000 SECT5  notype       Static       | .pdata
    Section length    C, #relocs    3, #linenums    0, checksum CE23E617
012 00000000 SECT5  notype       Static       | $pdata$main
013 00000000 SECT6  notype       Static       | .data
    Section length   2C, #relocs    0, #linenums    0, checksum C7B9A925
015 00000000 SECT6  notype       Static       | $SG10717
016 00000008 SECT6  notype       Static       | $SG10718
017 00000018 SECT6  notype       Static       | $SG10719
018 00000000 SECT7  notype       Static       | .chks64
    Section length   38, #relocs    0, #linenums    0, checksum        0

String Table Size = 0x1D bytes

  Summary

          38 .chks64
          2C .data
          68 .debug$S
          2F .drectve
           C .pdata
          5D .text$mn
           8 .xdata

... er? strnicmp is being imported, but not with the prepended underscore suggested by the Microsoft documentation. The reference is to the unadorned name.

So what's going on? Presumably I am misunderstanding something in the chain here. Is there a way for a function to be exported such that it does not show up in the dumpbin /exports output of any library?


Solution

  • It's in oldnames.lib. It didn't show up in the listing because it turns out that for a static library, you need to use dumpbin /symbols instead of /exports, otherwise it silently gives no output.