2011-08-22 104 views
4

我在安裝GCC 4.4.5的gentoo linux上。我可以使用gcc main.c -o main和命令./main正確地返回結果,從而編譯並鏈接此程序,而不會出現任何錯誤。鏈接多個C源文件

[main.c] 
#include <math.h> 
#include <stdio.h> 
int main(void) 
{ 
    double c = ceil(2.5); 
    printf("The ceil of 2.5 is %f\n", c); 
    return 0; 
} 

但是當我把小區的invokation到另一個源文件時,會出現問題。

[calc.h] 
#ifndef _CALC_H_ 
#define _CALC_H_ 
double myceil(double n); 
#endif 

[calc.c] 
#include <math.h> 
#include "calc.h" 
double myceil(double n) 
{ 
    return ceil(n); 
} 

[main1.c] 
#include <stdio.h> 
#include "calc.h" 
int main(void) 
{ 
    double c = myceil(2.5); 
    printf("The ceil of 2.5 is %f\n", c); 
    return 0; 
} 

使用命令GCC calc.c main1.c -o MAIN1發生,這樣的錯誤:

/tmp/cc6GhJvZ.o: In function `myceil': 
calc.c:(.text+0x19): undefined reference to `ceil' 
collect2: ld returned 1 exit status 

那麼,爲什麼煩人的錯誤 「未定義的引用」 發生在後一種情況?我知道這個錯誤可以通過添加一個庫-lm來消除,但是,我只想知道爲什麼gcc會在後一種情況下拋出錯誤。

+0

這個錯誤不會在osx或RHEL 6中顯示... –

+0

@ Foo,最近我在Vmware Workstation 7.0.0上安裝了rhel-workstation-6.0-i386-dvd.iso,但錯誤依然存在。 – machinarium

+0

哦我使用的是x64服務器版本 –

回答

5

我的猜測是,GCC優化ceil(2.5)一個常數,而ceil(n)不是恆定的,因爲編譯calc.cn不知道,它需要引用的函數。您可以通過查看組件輸出(gcc -S)來確認這一點。

更新:下面是GCC 4.2.1在x86上給了我類似的第一個例子一句:

.LC1: 
    .string "%f\n" 
    // [snip] 
main: 
    // [snip] 
    fldl .LC0 
    fstpl 4(%esp) 
    movl $.LC1, (%esp) 
    call printf 
    // [snip] 
.LC0: 
    .long 0 
    .long 1074266112 

在這裏,我們看到printf被稱爲具有double不變。

現在,如果我做同樣的你的第二個例子東西:

myceil: 
    // [snip] 
    fldl -8(%ebp) 
    fstpl (%esp) 
    call ceil 
    // [snip] 

在這裏,我們看到ceil被引用。

所以是的。我會說你的電話正在優化到一個不需要-lm的工作。

+0

請問您可以告訴我如何具體使用'gcc -S',或者一些教程?謝謝。 – machinarium

+0

用法示例:'gcc -S foo.c'。這將輸出一個名爲'foo.s'的文件。當然,您的平臺彙編語言的一些知識也會對您有所幫助。 – asveikau

+0

非常感謝。問題正是你說的。當我用'ceil(x)'代替'ceil(2.5)',其中x的值爲2.5時,引用錯誤就像我的後一種情況一樣。 – machinarium

0

如果您首先將main.c編譯爲main.o和calc.c以calc.o,然後將它們鏈接起來,是否可行?這通常是我所期望的(鏈接目標文件,而不是嘗試在單個命令行上編譯多個C文件)。

+0

感謝您的回覆。我使用下面的命令'gcc -c calc.c''gcc -c main1.c'和'gcc -o main1 calc.o main1.o',但仍然會出現同樣的錯誤。 – machinarium

2

gcc有一個列表built-in functionsceil就是其中之一。在我的OSX版本中,gcc在兩種情況下均使用內置ceil,因此-lm不是必需的。顯然你的Gentoo編譯器的行爲不同,在某些情況下只使用內置的ceil。如果您嘗試使用​​進行編譯,那麼您必須使用-lm進行兩次編譯。

+0

非常感謝。 – machinarium

+0

謝謝@mu。當我使用'gcc -fnobuilt -in main.c -o main'時,發生引用錯誤。看起來,在我的gentoo中,內置函數只接受常量參數,例如2.5在我以前的情況下。 – machinarium

+0

@machinarium:這很酷,我想它也被優化了,但我想我會提到內置的,因爲它們會導致一些令人困惑的行爲。可能是多文件問題,也可能是編譯器配置中的問題。 –