การอ้างอิงที่ไม่ได้กำหนดถึง `` pow 'และ `` floor'


124

ฉันกำลังพยายามสร้างเครื่องคำนวณ fibonacci อย่างง่ายในภาษา C แต่เมื่อรวบรวมgccบอกว่าฉันไม่มีฟังก์ชันธารและพื้น มีอะไรผิดปกติ

รหัส:

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

int fibo(int n);

int main() {
        printf("Fib(4) = %d", fibo(4));
        return 0;
}

int fibo(int n) {
        double phi = 1.61803399;

        return (int)(floor((float)(pow(phi, n) / sqrt(5)) + .5f));
}

เอาท์พุท:

gab@testvm:~/work/c/fibo$ gcc fib.c -o fibo
/tmp/ccNSjm4q.o: In function `fibo':
fib.c:(.text+0x4a): undefined reference to `pow'
fib.c:(.text+0x68): undefined reference to `floor'
collect2: ld returned 1 exit status

เนื่องจากความแม่นยำของจุดลอยตัวไม่ได้ไม่มีที่สิ้นสุดสิ่งนี้จะให้คำตอบที่ผิดสำหรับค่าที่ไม่มากนักของn
vonbrand


ดูเหมือนว่าจะมีวิธีแก้ปัญหาที่ง่ายกว่านั้นเพียงใช้ g ++ แทน: g ++ fib.c -o
fibo

คำตอบ:


242

คุณต้องคอมไพล์ด้วยแฟล็กลิงก์-lmดังนี้:

gcc fib.c -lm -o fibo

สิ่งนี้จะบอกให้ gcc เชื่อมโยงรหัสของคุณกับ lib คณิตศาสตร์ อย่าลืมใส่ค่าสถานะไว้หลังวัตถุที่คุณต้องการเชื่อมโยง


7
คุณช่วยอธิบายวิธีการเขียนจดหมายที่จะใส่หลัง -l ได้ไหม
Gabriele Cirulli

48
ดูใน / lib หรือ / usr / lib ไลบรารีทั้งหมดถูกตั้งชื่อlib<name>.aหรือlib<name>.so- เป็น "<name>" ที่คุณใส่ไว้หลังไฟล์-l. ในกรณีนี้ห้องสมุดคณิตศาสตร์เป็นชื่อดังนั้นเราจึงเรียกมันว่าlibm.so -lm
AMS

3
ขอบคุณ! ฉันใช้ googling เป็นเวลา 30 นาทีที่ผ่านมาและนี่เป็นการอ้างอิงครั้งแรกที่บอกว่าจะเชื่อมโยงไลบรารีตามวัตถุ
Dave Baghdanov

คุณยังสามารถใช้ LD_PRELOAD เพื่อบอกให้ ld runtime linker รวม libm.so ในแผนที่หน่วยความจำและตารางสัญลักษณ์ของกระบวนการเพื่อให้สัญลักษณ์เหล่านี้โหลดและทุกอย่างทำงานได้ตามที่คาดไว้
เปิดตัว

ขอบคุณสำหรับคำตอบ. แต่ใครช่วยบอกหน่อยได้ไหมว่าทำไมในกรณีของรหัสที่มีสองสามบรรทัดมันก็โอเคแม้ว่าฉันจะไม่รวม -lm ในขณะคอมไพล์
MItrajyoti Kusari

24

เพิ่ม -lm ให้กับตัวเลือกลิงก์ของคุณเนื่องจาก pow () และ floor () เป็นส่วนหนึ่งของไลบรารีคณิตศาสตร์:

gcc fib.c -o fibo -lm

9

เพื่อประโยชน์ของทุกคนที่อ่านสิ่งนี้ในภายหลังคุณต้องเชื่อมโยงกับเฟรดกล่าวว่า:

gcc fib.c -lm -o fibo

วิธีหนึ่งที่ดีในการค้นหาว่าคุณต้องเชื่อมโยงไลบรารีใดคือการตรวจสอบ man page ว่ามีอยู่หรือไม่ ตัวอย่างเช่นman powและman floorทั้งสองจะบอกคุณ:

เชื่อมโยงกับ-lm.

คำอธิบายสำหรับการเชื่อมโยงไลบรารีคณิตศาสตร์ในการเขียนโปรแกรม C - การเชื่อมโยงใน C


8

เกี่ยวกับคำตอบที่ Fuzzy ให้ไว้:

ฉันต้องทำอะไรที่แตกต่างออกไปเล็กน้อย

โครงการ -> คุณสมบัติ -> สร้าง C / C ++ -> การตั้งค่า -> GCC C Linker -> ไลบรารี

คลิกไอคอนเพิ่มสีเขียวเล็ก ๆ พิมพ์ m แล้วกดตกลง ทุกอย่างในหน้าต่างนี้จะใช้ -l โดยอัตโนมัติเนื่องจากเป็นไลบรารี


6

ในการหาจุดที่จะเพิ่ม -lm ใน Eclipse-IDE นั้นแย่มากดังนั้นฉันจึงต้องใช้เวลาพอสมควร

หากมีคนอื่นใช้ Edlipse ด้วยนี่คือวิธีเพิ่มคำสั่ง:

โครงการ -> คุณสมบัติ -> สร้าง C / C ++ -> การตั้งค่า -> GCC C Linker -> Miscelleaneous -> แฟล็ก Linker: ในฟิลด์นี้ให้เพิ่มคำสั่ง -lm


0

คำตอบทั้งหมดข้างต้นจะไม่สมบูรณ์ปัญหาที่นี่อยู่ในลิงเกอร์มากกว่าคอมไพเลอร์ld collect2: ld returned 1 exit statusเมื่อคุณกำลังรวบรวมสิ่งที่คุณfib.cต้องการ:

$ gcc -c fib.c
$ nm fib.o
0000000000000028 T fibo
                 U floor
                 U _GLOBAL_OFFSET_TABLE_
0000000000000000 T main
                 U pow
                 U printf

โดยnmแสดงสัญลักษณ์จากอ็อบเจ็กต์ไฟล์ คุณจะเห็นว่านี้ถูกรวบรวมโดยไม่ต้องข้อผิดพลาด แต่pow, floorและprintfฟังก์ชั่นมีการอ้างอิงที่ไม่ได้กำหนดตอนนี้ถ้าผมจะพยายามที่จะเชื่อมโยงนี้เพื่อปฏิบัติการ:

$ gcc fib.o
fib.o: In function `fibo':
fib.c:(.text+0x57): undefined reference to `pow'
fib.c:(.text+0x84): undefined reference to `floor'
collect2: error: ld returned 1 exit status

ฉันได้รับผลลัพธ์ที่คล้ายกันที่คุณได้รับ ในการแก้ปัญหานั้นฉันต้องบอกลิงค์เกอร์ว่าจะค้นหาข้อมูลอ้างอิงถึงที่ไหนpowและfloorเพื่อจุดประสงค์นี้ฉันจะใช้-lแฟล็กตัวเชื่อมmซึ่งมาจากlibm.soไลบรารี

$ gcc fib.o -lm
$ nm a.out
0000000000201010 B __bss_start
0000000000201010 b completed.7697
                 w __cxa_finalize@@GLIBC_2.2.5
0000000000201000 D __data_start
0000000000201000 W data_start
0000000000000620 t deregister_tm_clones
00000000000006b0 t __do_global_dtors_aux
0000000000200da0 t 
__do_global_dtors_aux_fini_array_entry
0000000000201008 D __dso_handle
0000000000200da8 d _DYNAMIC
0000000000201010 D _edata
0000000000201018 B _end
0000000000000722 T fibo
0000000000000804 T _fini
                 U floor@@GLIBC_2.2.5
00000000000006f0 t frame_dummy
0000000000200d98 t __frame_dummy_init_array_entry
00000000000009a4 r __FRAME_END__
0000000000200fa8 d _GLOBAL_OFFSET_TABLE_
                 w __gmon_start__
000000000000083c r __GNU_EH_FRAME_HDR
0000000000000588 T _init
0000000000200da0 t __init_array_end
0000000000200d98 t __init_array_start
0000000000000810 R _IO_stdin_used
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
0000000000000800 T __libc_csu_fini
0000000000000790 T __libc_csu_init
                 U __libc_start_main@@GLIBC_2.2.5
00000000000006fa T main
                 U pow@@GLIBC_2.2.5
                 U printf@@GLIBC_2.2.5
0000000000000660 t register_tm_clones
00000000000005f0 T _start
0000000000201010 D __TMC_END__

ตอนนี้คุณสามารถดูฟังก์ชั่นpow, ที่เชื่อมโยงกับfloorGLIBC_2.2.5

ลำดับพารามิเตอร์ก็สำคัญเช่นกันเว้นแต่ระบบของคุณจะได้รับการกำหนดค่าให้ใช้ไลบรารีที่ใช้ร่วมกันตามค่าเริ่มต้นระบบของฉันไม่ได้ดังนั้นเมื่อฉันออก:

$ gcc -lm fib.o
fib.o: In function `fibo':
fib.c:(.text+0x57): undefined reference to `pow'
fib.c:(.text+0x84): undefined reference to `floor'
collect2: error: ld returned 1 exit status

หมายเหตุ-lmแฟล็กก่อนอ็อบเจ็กต์ไฟล์ ดังนั้นโดยสรุปแล้วให้เพิ่ม-lmแฟล็กหลังแฟล็กและพารามิเตอร์อื่น ๆ ทั้งหมดเพื่อให้แน่ใจ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.