【问题标题】:sscanf() causes link to fail when powl() is present当 powl() 存在时,sscanf() 导致链接失败
【发布时间】:2012-01-05 03:49:16
【问题描述】:

当我编译下面的精简程序时,我从链接器收到以下错误:

$ gcc -std=c99 -O3 powltest.c -o powltest
/tmp/ccYkWTGI.o: In function `main':
powltest.c:(.text+0x7a): undefined reference to `powl'
collect2: ld returned 1 exit status

如果我用sscanf() 注释掉该行,则编译成功,并且由于功能减少,程序可以正确运行。如果我改为注释掉包含 powl()

的行,它也可以工作
#include <stdio.h>
#include <math.h>

int main(int argc, char *argv[])
{
    unsigned int bits = 5;
    unsigned int n = 0;
    unsigned long long start = 0;

    n = sscanf(argv[1], "%u", &bits);
    printf("%u\n", bits);
    start = powl(2, bits) - 1;
    printf("%llu\n", start);
}

以下是版本:

$ gcc --version
gcc (Ubuntu 4.4.1-4ubuntu9) 4.4.1
$ ld --version
GNU ld (GNU Binutils for Ubuntu) 2.20

同样的结果:

$ gcc --version
gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-51)
$ ld --version
GNU ld version 2.17.50.0.6-14.el5 20061020

运行:

$ ./powltest 42    # commented-out sscanf()
5
31
$ ./powltest 42    # commented-out powl()
42
0

我做错了什么?

【问题讨论】:

    标签: c scanf pow


    【解决方案1】:

    当您注释掉sscanf 调用时,所有变量都有在编译时已知的值,并且编译器的优化器能够确定powl 调用的结果,而无需实际调用math.h 中声明的任何函数.

    当您取消注释 scanf 调用时,优化器无法在编译时确定 powl 调用的结果,因此它必须调用真正的 powl 函数,该函数位于您的单独库中必须使用-lm 链接到您的程序。

    【讨论】:

    • 很好地解释了为什么在编译器中启用优化时注释掉 sscanf 会起作用。
    【解决方案2】:

    与数学库 (-lm) 的链接消除了 undefined reference to 'powl' 错误:

    gcc -o test test.c -lm
    

    这在powl 的手册页中也有说明:

    概要

    #include <math.h>
    
    double pow(double x, double y);
    float powf(float x, float y);
    long double powl(long double x, long double y);
    

    与 -lm 链接。

    编辑:只有在 sscanf 被注释掉时,如果它也被优化编译(-OX),它只会为我编译,dreamlax 在他的回答中有原因。

    【讨论】:

    • 这并不能解释在没有sscanf 调用的情况下编译和正常工作的其他现象。
    • @dreamlax 好点 - 我没有详细阅读问题 - 很好的发现。
    • @dreamlax:是的,好点,我没有那样看问题 - 至于为什么它有时会编译 - 而是如何解决问题的发生。跨度>
    • 建议:库应该在(链接器)命令行上跟随目标文件。
    • 对于静态库,在命令行上按顺序扫描库,只有满足不满足引用的目标文件才会从库中取出。因此,对于静态链接,库遵循引用库的目标文件至关重要。共享库是不同的,一些链接器会在列出库时扫描它们并确保它们在运行时加载,但这可能导致动态加载器加载并不真正需要的库。有时,链接器不会从目标文件之前列出的共享库中提取符号。
    猜你喜欢
    • 2019-05-06
    • 1970-01-01
    • 1970-01-01
    • 2014-02-03
    • 2011-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-03
    相关资源
    最近更新 更多