为什么 Linux 中没有库说明符就没有错误?

Why no error without library specifiers in Linux?

我目前是一名学生,正在学习操作系统并使用 Linux 作为 OS 进行练习。当我们开始使用多线程应用程序并开始练习它们时(主要是 pthread_create() 和 pthread_join() ),class 遇到的最常见错误之一是当编译他们使用:

gcc -Wall homework.c

而不是:

gcc -Wall -lpthread homework.c

我的问题是,即使代码中使用的函数需要 pthread 库,为什么编译器和链接器在没有 compiled/linked 和 -lpthread 说明符时不抛出错误。我的导师似乎也不知道原因。这只是学校设置我们系统的方式吗?所有 Linux 环境都会发生这种情况吗?为什么没有抛出链接器错误?

无法重现:

#include <pthread.h>

void *thread(void *arg)
{
    (void) arg;
    return 0;
}

int main(void)
{
    pthread_t t;
    pthread_create(&t, 0, thread, 0);
    return 0;
}

尝试 link 没有 libpthread:

> gcc -Wall -o thread thread.c
/tmp/ccyyu0cn.o: In function `main':
thread.c:(.text+0x2e): undefined reference to `pthread_create'
collect2: error: ld returned 1 exit status

edit: 你可以用nm -D检查库中定义的符号,例如就我而言:

> nm -D /lib/x86_64-linux-gnu/libc.so.6 | grep pthread_create
> nm -D /lib/x86_64-linux-gnu/libpthread.so.0 | grep pthread_create
00000000000082e0 T pthread_create

(所以 pthread_create 而不是 libc 中找到,但确实在 libpthread 中)

edit2: 您声称观察到的行为的唯一可能原因是 linked 默认 libc,也许 libgcc)定义了 pthread_create。那么它可能仍然依赖于仅在 libpthread 中定义的事物。我现在想知道某些特定版本是否真的如此。请给予反馈。

@FelixPalmen 的回答的附加假设。 pthread 可以传递给 gcc 规范中声明的链接器。 gcc 可以使用内置规范或从文件中读取它。

实验

默认情况下,当我尝试在没有 -lpthreads:

的情况下构建示例时,我的系统链接器打印错误
serga@XXXXX:~$ gcc ./thread.c -o thread
/tmp/ccHgCRzO.o: In function `main':
thread.c:(.text+0x29): undefined reference to `pthread_create'
collect2: error: ld returned 1 exit status

首先我检测到which files gcc tries to use as spec:

serga@XXXXX:~$ strace gcc 2>&1 | grep spec
access("/usr/lib/gcc/i686-linux-gnu/5/specs", R_OK) = -1 ENOENT (No such file or directory)
access("/usr/lib/gcc/i686-linux-gnu/5/../../../../i686-linux-gnu/lib/i686-linux-gnu/5/specs", R_OK) = -1 ENOENT (No such file or directory)
access("/usr/lib/gcc/i686-linux-gnu/5/../../../../i686-linux-gnu/lib/specs", R_OK) = -1 ENOENT (No such file or directory)
access("/usr/lib/gcc/i686-linux-gnu/specs", R_OK) = -1 ENOENT (No such file or directory)

然后我创建自己的规范 getting build-in one 并将其放入上一步中获得的路径中:

    serga@XXXXX:~$ sudo gcc -dumpspecs >/usr/lib/gcc/i686-linux-gnu/5/specs

我将 -lpthread 一一插入到 spec 文件的 *link:*lib:*libgcc: 部分。在所有情况下,gcc 都可以在不明确提及 pthread 库的情况下构建程序:

serga@XXXXX:~$ gcc ./thread.c -o thread && echo "completed"
completed

明白了!!!

检测 gcc 是否使用任何额外的规范文件

需要看下的输出(我用的是gcc-5.1.0):

serga@XXXXX:~$ gcc -v 2>&1 | head -1
  • 如果 gcc 使用特定文件中的规范,您将看到下一个:

    Reading specs from /usr/lib/gcc/i686-linux-gnu/5/specs
    
  • 否则:

    Using built-in specs.
    

    您可以看到这样做的内置规范:

    serga@XXXXX:~$ gcc -dumpspecs
    

检测是否默认与 pthread 链接

需要在获取的规范文件中查看与链接器相关的部分中 -lpthread 的任何外观。

Spec file reference