Ubuntu Bash 上 windows 上的 gcc 问题与数学库

Issue with gcc on Ubuntu Bash on windows with math library

我有一个使用“-lm”标志来包含数学库的生成文件。我还为每个 .c 文件包含了#include。 我仍然遇到错误和 "undefined reference" 数学运算,例如 exp、floor 和 pow 等

在 windows Ubuntu 上使用 bash。

我的终端输出的副本:

labyu@DESKTOP-U037B9F:~/software/BICseq2/NBICseq-norm_v0.2.4$ make
gcc -g -O2 -Wall -lm   -c -o combineFile/combine.o combineFile/combine.c
gcc -g -O2 -Wall -lm   -c -o lib/read.o lib/read.c
lib/read.c: In function ‘read_table’:
lib/read.c:74:14: warning: variable ‘flag’ set but not used [-Wunused-but-set-variable]
  int i=0,j=0,flag=1,low_mmry = 40000, is_num=0,k;
              ^
gcc -g -O2 -Wall -lm combineFile/combine.o lib/read.o -o combineFile/combineFile
gcc -g -O2 -Wall -lm   -c -o DataPrepare/DtaPrep.o DataPrepare/DtaPrep.c
gcc -g -O2 -Wall -lm   -c -o lib/statlib.o lib/statlib.c
gcc -g -O2 -Wall -lm  DataPrepare/DtaPrep.o lib/read.o lib/statlib.o -o DataPrepare/PrepPois
DataPrepare/DtaPrep.o: In function `print_oneline':
/home/labyu/software/BICseq2/NBICseq-norm_v0.2.4/DataPrepare/DtaPrep.c:593: undefined reference to `pow'
/home/labyu/software/BICseq2/NBICseq-norm_v0.2.4/DataPrepare/DtaPrep.c:591: undefined reference to `log'
DataPrepare/DtaPrep.o: In function `calculate_bias':
/home/labyu/software/BICseq2/NBICseq-norm_v0.2.4/DataPrepare/DtaPrep.c:685: undefined reference to `pow'
/home/labyu/software/BICseq2/NBICseq-norm_v0.2.4/DataPrepare/DtaPrep.c:690: undefined reference to `exp'
/home/labyu/software/BICseq2/NBICseq-norm_v0.2.4/DataPrepare/DtaPrep.c:681: undefined reference to `log'
DataPrepare/DtaPrep.o: In function `fprint_gc_bin':
/home/labyu/software/BICseq2/NBICseq-norm_v0.2.4/DataPrepare/DtaPrep.c:810: undefined reference to `floor'
DataPrepare/DtaPrep.o: In function `fprintf_predicted':
/home/labyu/software/BICseq2/NBICseq-norm_v0.2.4/DataPrepare/DtaPrep.c:850: undefined reference to `exp'
/home/labyu/software/BICseq2/NBICseq-norm_v0.2.4/DataPrepare/DtaPrep.c:860: undefined reference to `floor'
DataPrepare/DtaPrep.o: In function `calculate_bias':
/home/labyu/software/BICseq2/NBICseq-norm_v0.2.4/DataPrepare/DtaPrep.c:749: undefined reference to `exp'
lib/statlib.o: In function `db_shuffle':
/home/labyu/software/BICseq2/NBICseq-norm_v0.2.4/lib/statlib.c:56: undefined reference to `floor'
lib/statlib.o: In function `db_shuffle_int':
/home/labyu/software/BICseq2/NBICseq-norm_v0.2.4/lib/statlib.c:71: undefined reference to `floor'
lib/statlib.o: In function `rgamma1':
/home/labyu/software/BICseq2/NBICseq-norm_v0.2.4/lib/statlib.c:99: undefined reference to `log'
/home/labyu/software/BICseq2/NBICseq-norm_v0.2.4/lib/statlib.c:100: undefined reference to `pow'
/home/labyu/software/BICseq2/NBICseq-norm_v0.2.4/lib/statlib.c:103: undefined reference to `pow'
/home/labyu/software/BICseq2/NBICseq-norm_v0.2.4/lib/statlib.c:104: undefined reference to `exp'
/home/labyu/software/BICseq2/NBICseq-norm_v0.2.4/lib/statlib.c:90: undefined reference to `log'
collect2: error: ld returned 1 exit status
make: *** [PrepPois] Error 1

但是,当我制作一个示例程序时,例如:test.c

#include <stdio.h>
#include <math.h>

int main(void)
{
   int number;
   number = pow(10,2);
   printf("%d\n", number);
   return 0;
 }

即使没有 -lm 标志,我也可以使用 gcc test.c,并且编译正常。

这是一个错误吗?

在您的测试用例中,由于所有数据都是常量,因此编译器似乎直接计算了值(这可能取决于编译器,但最新版本的 gcc 似乎可以很好地处理这个问题)

反汇编代码(x86)的时候看的一清二楚

   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   48 83 ec 30             sub    [=10=]x30,%rsp
   8:   e8 00 00 00 00          callq  d <main+0xd>

direct 100 value passed to printf at the line below

   d:   c7 45 fc 64 00 00 00    movl   [=11=]x64,-0x4(%rbp)
  14:   8b 45 fc                mov    -0x4(%rbp),%eax
  17:   89 c2                   mov    %eax,%edx
  19:   48 8d 0d 00 00 00 00    lea    0x0(%rip),%rcx        # 20 <main+0x20>
  20:   e8 00 00 00 00          callq  25 <main+0x25>
  25:   b8 00 00 00 00          mov    [=11=]x0,%eax
  2a:   90                      nop
  2b:   48 83 c4 30             add    [=11=]x30,%rsp
  2f:   5d                      pop    %rbp
  30:   c3                      retq
  31:   90                      nop

我已将代码更改为:

#include <stdio.h>
#include <math.h>

int main(void)
{
   int number;
   int v=10;
   number = pow(v,2);
   printf("%d\n", number);
   return 0;
 }

现在,当我 nm 文件时,我得到:

>nm simplemath.o
0000000000000000 b .bss
0000000000000000 d .data
0000000000000000 p .pdata
0000000000000000 r .rdata
0000000000000000 r .rdata$zzz
0000000000000000 t .text
0000000000000000 r .xdata
                 U __main
0000000000000000 T main
                 U pow
                 U printf

在我引入变量之前,没有引用pow符号。编译器静态计算。

反汇编显示了更复杂的代码,使用浮点寄存器和所有。

0000000000000000 <main>:
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   48 83 ec 40             sub    [=14=]x40,%rsp
   8:   e8 00 00 00 00          callq  d <main+0xd>
   d:   c7 45 fc 0a 00 00 00    movl   [=14=]xa,-0x4(%rbp)
  14:   66 0f ef c0             pxor   %xmm0,%xmm0
  18:   f2 0f 2a 45 fc          cvtsi2sdl -0x4(%rbp),%xmm0
  1d:   48 b8 00 00 00 00 00    movabs [=14=]x4000000000000000,%rax
  24:   00 00 40
  27:   48 89 45 e8             mov    %rax,-0x18(%rbp)
  2b:   f2 0f 10 4d e8          movsd  -0x18(%rbp),%xmm1
  30:   e8 00 00 00 00          callq  35 <main+0x35>  <== the linker wil add the call to pow here
  35:   f2 0f 2c c0             cvttsd2si %xmm0,%eax
  39:   89 45 f8                mov    %eax,-0x8(%rbp)
  3c:   8b 45 f8                mov    -0x8(%rbp),%eax
  3f:   89 c2                   mov    %eax,%edx
  41:   48 8d 0d 00 00 00 00    lea    0x0(%rip),%rcx        # 48 <main+0x48>
  48:   e8 00 00 00 00          callq  4d <main+0x4d>
  4d:   b8 00 00 00 00          mov    [=14=]x0,%eax
  52:   90                      nop
  53:   48 83 c4 40             add    [=14=]x40,%rsp
  57:   5d                      pop    %rbp
  58:   c3                      retq

但令我惊讶的是,不需要 -lm,没有它也可以链接。 最新的 gcc 版本必须默认包含它,因为它经常被使用。也许有人可以确认。你的版本似乎需要它,我的不需要 (gcc 4.9.4)