MinGW 中定义的标准 C I/O 函数在哪里?

问题描述 投票:0回答:2

我知道使用GCC时,标准I/O函数(例如

printf
fprintf
等)是在静态库
libc.a
中定义的。但是,我需要知道它们在 MinGW 环境中的何处定义,该环境没有
libc.a
。在我的 MinGW 安装中,我确实找到了以下库:
libcap.a
libcfgmgr32.a
libcoldname.a
libcomctl32.a
libcomdlg32.a
libcrtdll.a
libcrypt32.a
libctl3d32.a
。然而,我对这些是否与我想要的相关一无所知。

本质上,我需要知道标准C I/O函数在MinGW环境中定义在哪里。


作为更新,这些是默认情况下的所有 MinGW 链接库:

libmingw32.a
libmoldname.a
libmingwex.a
libmsvcrt.a
libadvapi32.a
libshell32.a
libuser32.a
。我想它可能是(或以某种方式连接到)其中之一?

c windows mingw mingw-w64
2个回答
4
投票

这比您希望的更复杂,因为在 MinGW 环境中可以通过多种不同的方式定义函数:

  1. 作为头文件中的内联函数。
  2. 作为静态库文件中的符号(即
    .a
    )。
  3. 作为导入库 (
    .a
    ) 中的符号,在运行时从 DLL 导入具有相似名称的函数。该 DLL 可以是 Windows 的一部分,也可以是 MinGW 的一部分。

所以我们假设

test.c
是一个基本的 C 语言 hello world 程序,它从
printf
调用
main

运行

gcc -S test.c
,然后运行
less test.s
以查看 GCC 为此代码生成的程序集。如果您的 MinGW 设置与我的一样(MSYS2 中的 MINGW64 环境),您将看到 test.s 实际上包含
printf
的代码。这告诉我们
printf
是在 MinGW 标头中的某处定义的。如果你仔细观察程序集,你会发现它基本上只是调用
__mingw_vfprintf

现在运行

gcc test.c -g -o test -Wl,-Map=test.map
less test.map
。搜索
__mingw_vfprintf
,找出它的来源。就我而言,它来自
C:/msys64/mingw64/lib/libmingwex.a

您可以尝试运行

objdump -d /mingw64/lib/libmingwex.a
来查看
__mingw_vfprintf
的编译代码,但效果不太好:它似乎没有显示
__mingw_vfprintf
调用的三个函数的名称。幸运的是,GDB 可以向我们展示这一点。您已经使用之前的命令编译了
test.exe
,因此运行
gdb ./test.exe
来启动调试器,然后在其中运行以下命令:

break __mingw_vfprintf
run
layout asm

请注意,第一个命令打印出

__mingw_vfprintf
的源文件名称(在构建服务器上),这可能很有用。

最后的命令向我们展示了

__mingw_vfprintf
中的程序集,我们可以看到它调用了三个函数。它调用的最有趣的函数是
__mingw_pformat

运行

break __mingw_pformat
continue
跳转到该函数。该函数中发生了很多事情。您可以使用调试器深入研究它或通过查看源代码来获取更多信息。它可能在某个时刻调用
msvcrt.dll
或其他一些 Windows DLL 中的函数。

解决此问题的另一种方法是查看运行时从 DLL 导入哪些函数。为此,请运行

objdump -p test.exe | less
并查找“导入表”。如果您的环境与我的一样,您将看到
fprintf
vfprintf
以及其他几个 C I/O 函数在运行时从
msvcrt.dll
(Windows 的一部分)导入。这是一个非常重要的 DLL,它是传统 MinGW 环境的基础,但是您可以通过多种方式配置 MinGW,让其使用不同的基础(即较新版本的 DLL 或 UCRT)。


0
投票

我编译了一个使用

printf
函数并使用 MinGW-w64 链接器(ld.exe)的目标文件(.o),我测试发现以下命令能够执行成功的链接以生成.exe文件:

  • ld.exe my_prog.o -o my_prog.exe -L"%path_to_MinGW%\x86_64-w64-mingw32\lib" -lcrtdll

    (使用
    libcrtdll.a
    进行链接)
  • ld.exe my_prog.o -o my_prog.exe -L"%path_to_MinGW%\x86_64-w64-mingw32\lib" -lmsvcrt

    (使用
    libmsvcrt.a
    进行链接)
  • ld.exe my_prog.o -o my_prog.exe -L"C:\Windows\System32" -lmsvcrt

    (直接使用
    msvcrt.dll
    进行链接)

所有这些都成功生成了

my_prog.exe
应用程序。但是,对于使用开关
-lcrtdll
的情况,程序无法启动,并抛出错误:在我的系统上找不到
crtdll.dll

对于其他两个命令,应用程序启动并成功运行(显然,这两个命令在运行时使用的

msvcrt.dll
在我的系统上可用)。

我对

crtdll.dll
进行了快速搜索,发现该 DLL 主要在旧版 Windows 版本上用作 C 运行时库 (CRT),而现代 Windows 版本则使用
msvcrt.dll
作为 CRT图书馆。我没有对此进行广泛阅读,但任何感兴趣的人都可以查看:

https://mingw-users.narkive.com/SHwKXuDL/msvcrt-vs-crtdll

https://learn.microsoft.com/en-us/troubleshoot/developer/visualstudio/cpp/libraries/use-c-run-time

© www.soinside.com 2019 - 2024. All rights reserved.