当编译一个C程序时,它按照预处理器、编译器、汇编程序、链接器的顺序进行。链接器的主要任务之一是使库函数的代码可用于程序。链接器可以以静态或动态两种方式链接它们。。
stdio。h
只包含声明,其中没有定义。我们只包括stdio。h
在程序中告诉编译器函数的返回类型和名称例如(printf(),scanf(),getc(),putc()…)
那么在下面的示例程序中,如何链接
printf()
和scanf()
?
如果是动态链接,哪个“DLL”负责链接
全部“C”库是否动态链接到程序
#include "stdio.h"
int main()
{
int n;
printf("Enter an integer\n");
scanf("%d", &n);
if (n%2 == 0)
printf("Even\n");
else
printf("Odd\n");
return 0;
}
-static-libstdc++
当g程序用于链接C程序时,它通常会自动链接到libstdc。如果libstdc作为一个共享库可用,并且没有使用-static选项,那么这将链接libstdc的共享版本。那通常很好。但是,有时可以冻结程序使用的libstdc版本,而不必一直使用完全静态的链接。-static libstdc选项指示g驱动程序静态链接libstdc,而不必静态链接其他库。
有关更多详细信息,请查看此线程。我如何静态链接标准库到我的c程序?
通常,标准C库是动态链接的。这主要是因为一旦一个程序被静态链接,其中的代码就永远固定了。如果有人发现并修复了printf
或scanf
中的错误,那么每个程序都必须再次链接才能获取固定的代码。
在动态链接的情况下,所有可执行文件(链接后创建)都不包含printf
或scanf
的代码副本。如果新的、固定的printf版本可用,则会在运行时获取该版本。
匿名用户
我想你想问的问题是:“我知道像printf
和scanf
这样的函数是由C运行库实现的。但是我可以使用它们,而不用告诉我的编译器和/或IDE将我的程序链接到C运行库。为什么我不需要这样做呢?”
这个问题的答案是:“不需要与C运行时库链接的程序非常罕见。即使您没有显式使用任何库函数,您仍然需要启动代码,并且编译器可能会发出对memcpy
、浮点仿真函数等的“引擎盖下”调用。因此,为了方便起见mpiler会自动将您的程序链接到C运行时库,除非您告诉它不要这样做。”
您必须查阅编译器的文档,以了解如何告诉编译器不要在C运行时库中链接。GCC使用-nostlib
命令行选项。下面,我将演示如何通过跳转来实现这一目标。。。
$ cat > test.c
#include <stdio.h>
int main(void) { puts("hello world"); return 0; }
^D
$ gcc -nostdlib test.c && { ./a.out; echo $?; }
/usr/bin/ld: warning: cannot find entry symbol _start
/tmp/cc8svIx5.o: In function ‘main’:
test.c:(.text+0xa): undefined reference to ‘puts’
collect2: error: ld returned 1 exit status
放
显然在C库中,但这个神秘的“入口符号_start
”也是如此。关闭C库,你也必须自己提供...
$ cat > test.c
int _start(void) { return 0; }
^D
$ gcc -nostdlib test.c && { ./a.out; echo $?; }
Segmentation fault
139
它现在链接了,但是我们得到了一个分段错误,因为\u start
无处可返回!操作系统希望它调用\u exit
。好的,让我们这样做。。。
$ cat > test.c
extern void _exit(int);
void _start(void) { _exit(0); }
^D
$ gcc -nostdlib test.c && { ./a.out; echo $?; }
/tmp/ccuDrMQ9.o: In function `_start':
test.c:(.text+0xa): undefined reference to `_exit'
collect2: error: ld returned 1 exit status
... nuts,\u exit
也是C运行时库中的一个函数!原始系统调用时间。。。
$ cat > test.c
#include <unistd.h>
#include <sys/syscall.h>
void _start(void) { syscall(SYS_exit, 0); }
^D
$ gcc -nostdlib test.c && { ./a.out; echo $?; }
/tmp/cchtZnbP.o: In function `_start':
test.c:(.text+0x14): undefined reference to `syscall'
collect2: error: ld returned 1 exit status
...不,syscall
也是C运行时中的一个函数。我想我们只需要使用组装!
$ cat > test.S
#include <sys/syscall.h>
.text
.globl _start
.type _start, @function
_start:
movq $SYS_exit, %rax
movq $0, %rdi
syscall
$ gcc -nostdlib test.S && { ./a.out; echo $?; }
0
这最终奏效了。在我的电脑上。它不能在不同的操作系统上工作,因为系统调用的程序集级别约定不同。
您现在可能想知道,如果您必须下降到汇编语言只是为了进行系统调用,那么-nostdlib到底有什么好处。它旨在用于编译完全独立的低级系统程序,如引导加载程序、内核和C运行时本身(部分)——无论如何,这些程序都必须实现自己的一切。
如果我们从头再来一遍,分离出一个低级别的独立于语言的运行时可能很有意义,只需要syscall包装器,独立于语言的进程启动代码,以及任何语言的编译器可能需要调用的“幕后”函数(memcpy
,\u Unwind\u RaiseException
,\u muldi3
,诸如此类)。这个想法的问题是它很快就会受到任务爬行的影响-你是否包括errno
?通用线程原语?(哪一个,用哪一种语义?)动态链接器?malloc
的一个实现,上面需要哪些东西?Windows的ntdll。dll从这个概念开始,在Windows 10中是1.8MB的磁盘,比libc稍大。所以
ld。因此,在我的Linux分区上。而且编写一个只使用ntdll的程序是非常罕见和困难的。dll
,即使您是Microsoft(我唯一确定的示例是csrss.exe
,它也可能是一个内核组件)。
静态链接方法:静态链接的时候,载入代码就会把程序会用到的动态代码或动态代码的地址确定下来 静态库的链接可以使用静态链接,动态链接库也可以使用这种方法链接导入库 动态链接方法:使用这种方式的程序并不在一开始就完成动态链接,而是直到真正调用动态库代码时,载入程序才计算(被调用的那部分)动态代码的逻辑地址,然后等到某个时候,程序又需要调用另外某块动态代码时,载入程序又去计算这部分代码的逻辑地址,所以,这
在编译Linux程序时,我们经常会看到动态链接和静态链接这两个术语。这两个术语中是我Linux的共享函数库(shared libraries)相关的。共享函数库就象Windows系统里的.dll文件,它里面包含有很多程序常用的函数。为了方便程序开发和减少程序的冗余,程序当中就不用包含每个常用函数的拷贝,只是在需要时调用系统中共享函数库中常函数功能即可。这种方式我们称之为动态链接(Dynamical
主要内容:静态链接库,动态链接库,总结我们知道,C、C++程序从源文件到生成可执行文件需经历 4 个阶段,分别为预处理、编译、汇编和链接,本节将重点围绕链接阶段,对静态链接库和动态链接库做详细的讲解。 有关链接操作的具体细节,感兴趣的读者可阅读《 到底什么是链接,它起到了什么作用?》和《 符号——链接的粘合剂》这两节。总的来说链接阶段要完成的工作,就是将同一项目中各源文件生成的目标文件以及程序中用到的库文件整合为一个可执行文件。 通过
问题内容: 在Linux中,下载了程序源并希望将其静态链接。我那里有一个巨大的Makefile 编译。预言这有点太笼统了,但是如何使二进制文件静态链接? 编辑:这样做的原因是要确保二进制文件没有依赖性(或至少尽可能少),从而使其可以在任何基于Linux的计算机上运行,甚至可以在没有Internet连接和未更新的Linux上运行。 问题答案: 大多数生成的脚本将允许您进行静态构建: 如果这样不起
问题内容: 我正在编写一个与GNU GPL不兼容的跨平台应用程序。我当前面临的主要问题是该应用程序与glibc和libstdc ++动态链接,并且几乎所有对库的新更新都不向后兼容。因此,在我的应用程序中会看到随机崩溃。 解决方法是,将应用程序的二进制文件分发在几个不同的系统(具有不同的C / C 运行时版本)上编译。但我要没有这个。所以我的问题是,请牢记许可和所有注意事项,我可以静态链接glibc
问题内容: 这些对象调用之间有什么区别? 非静态: 静态的: 而且在内部为什么还要对函数使用static属性? 例: 问题答案: 静态函数,根据定义,不能也不依赖于该类的任何实例属性。也就是说,它们不需要类的实例来执行(因此,可以如您所显示的那样执行,而无需先创建实例)。从某种意义上讲,这意味着该函数不必(也永远不需要)依赖于类的成员或方法(公共或私有)。