为什么 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
的任何外观。
我目前是一名学生,正在学习操作系统并使用 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
的任何外观。