gcc 是怎么找到 system 函数的定义(实现)的? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
rookiemaster
V2EX    C

gcc 是怎么找到 system 函数的定义(实现)的?

  •  
  •   rookiemaster 2024-03-20 10:23:35 +08:00 4001 次点击
    这是一个创建于 588 天前的主题,其中的信息可能已经有所发展或是发生改变。

    程序如下:

    int main() { system("echo hello world"); } 

    使用 gcc 编译时会警告找不到 system 的声明:

    DoubleHash.c: In function ‘main’: DoubleHash.c:3:5: warning: implicit declaration of function ‘system’ [-Wimplicit-function-declaration] 3 | system("echo hello world"); | ^~~~~~ 

    但是程序仍然可以运行,我想知道编译器是怎么找到 system 的定义的?

    19 条回复    2024-07-12 13:22:23 +08:00
    ho121
        1
    ho121  
       2024-03-20 10:29:20 +08:00
    应该是链接 glibc 时找到的,毕竟大部分程序都需要 glibc

    我猜的。
    geelaw
        2
    geelaw  
       2024-03-20 10:43:00 +08:00 via iPhone   2
    system 是标准库函数,链接的时侯默认是带标准库的,所以找到了。

    C 语言没有函数重载,不需要复杂的名称修饰,int system(…); 和 int system(char const *); 链接的时候去找的是同一个符号,前者是隐式声明的结果,后者是标准库的声明,故隐式声明的调用可以链接到标准库函数。
    seers
        3
    seers  
       2024-03-20 10:54:25 +08:00 via Android
    运行时候会去 ld.conf 找符号
    yolee599
        4
    yolee599  
       2024-03-20 11:08:45 +08:00   1
    int add(int a, int b) 和 float add(float a, int b, int c) 的符号是同一个,运行的时候函数会通过栈传递参数。编译的时候是通过符号来链接的,如果在头文件定义了这个函数,类型不匹配编译会出错,而如果头文件不定义,只要符号对上了编译就会成功,只会报警告。
    churchmice
        5
    churchmice  
       2024-03-20 11:30:09 +08:00
    推荐你看一下 link & loader
    wodexinhaoleng
        6
    wodexinhaoleng  
       2024-03-20 12:21:28 +08:00   1
    问题的方向错了,这个问题你应该问这个警告是从哪来的

    因为 C 语言最初的设计上,函数调用本来就是不需要声明的。只是后面的编译器保留了兼容性
    proxytoworld
        7
    proxytoworld  
       2024-03-20 12:47:09 +08:00
    你不熟悉程序编译过程,首先 gcc 会先生成.a 文件,而后进行链接,在链接的时候找到了 system ,所以能编译出来,system 在 libc 里面。如果你使用一个不存在的函数,在链接的时候找不到,就会报错了。
    pagxir
        8
    pagxir  
       2024-03-20 13:02:43 +08:00 via Android
    函数声明在 stdlib.h ,实现自然在 libc ,默认都会链接 libc 的。不 include stdlib 直接用 system 大概率在 64 位系统下程序崩溃
    653513754
        9
    653513754  
       2024-03-20 13:43:59 +08:00
    推荐你看一下编译之后的汇编,可以清楚的看出来系统是怎么找到 system 的
    ysc3839
        10
    ysc3839  
       2024-03-20 16:06:41 +08:00 via Android
    是 implicit-function-declaration ,直接用你给的参数类型作为定义了
    rookiemaster
        11
    rookiemaster  
    OP
       2024-03-20 16:12:55 +08:00 via iPhone
    @geelaw 那隐式声明与实际调用的时候参数对不上为啥编译会通过呢
    leonshaw
        12
    leonshaw  
       2024-03-20 16:42:30 +08:00
    @rookiemaster 当作隐式函数声明 int system(); 按 ABI 调用就行了
    geelaw
        13
    geelaw  
       2024-03-20 16:45:36 +08:00 via iPhone
    @geelaw #2 更正:隐式声明是 int system();

    #11 空白的参数列表的意思是没有提供参数列表信息,并没有对不上。
    nuk
        14
    nuk  
       2024-03-20 16:46:40 +08:00
    隐式声明,理论上默认的函数声明会是 int f(void),但是 gcc 实际上传递了参数,而且因为 X64 是 fastcall ,前几个参数用寄存器传递,所以就算参数数量对不上,也不会崩溃。你可以试试这样,一样不会崩溃:
    system("echo hello world");
    system("echo hello world", "echo hello world");
    cnbatch
        15
    cnbatch  
       2024-03-20 19:50:26 +08:00
    “隐式声明与实际调用的时候参数对不上”

    不是对不上,而是因为 C 语言的特性。

    在其它编程语言当中(比如 C++、Java 、C# ),int system();表示该函数不接受参数传入。

    但 C 语言不同,int system(); 表示参数情况未知,是个笼统的声明。
    而 int system(void) 才是其它编程语言 int system();的意思。

    这里有比较详细的说明,在页面尾部 Note 那一节,句子以“Unlike in C++”开头:
    https://en.cppreference.com/w/c/language/function_declaration
    rookiemaster
        16
    rookiemaster  
    OP
       2024-03-20 20:00:20 +08:00
    @cnbatch 谢谢
    zeroxia
        17
    zeroxia  
       2024-03-23 12:34:10 +08:00
    @nuk 到底默认是 `int f()` 还是 `int f(void)`?
    nuk
        18
    nuk  
       2024-03-23 17:50:50 +08:00
    @zeroxia int f(),我说错了,不指定参数类型
    chisato
        19
    chisato  
       2024-07-12 13:22:23 +08:00
    #include <assert.h>
    #include <ctype.h>
    #include <errno.h>
    #include <float.h>
    #include <limits.h>
    #include <stdarg.h>
    #include <stdbool.h>
    #include <stddef.h>
    #include <stdint.h>

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1082 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 18:29 PVG 02:29 LAX 11:29 JFK 14:29
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86