ทำไมคุณต้องลิงค์ห้องสมุดคณิตศาสตร์ใน C?


254

หากฉันรวม<stdlib.h>หรือ<stdio.h>อยู่ในโปรแกรม C ฉันไม่จำเป็นต้องเชื่อมโยงสิ่งเหล่านี้เมื่อรวบรวม แต่ฉันต้องเชื่อมโยงกับ<math.h>ใช้-lmกับ gcc ตัวอย่างเช่น:

gcc test.c -o test -lm

อะไรคือสาเหตุของสิ่งนี้? เหตุใดฉันจึงต้องเชื่อมโยงห้องสมุดคณิตศาสตร์อย่างชัดเจน แต่ไม่ใช่ห้องสมุดอื่น

คำตอบ:


249

ฟังก์ชั่นในstdlib.hและstdio.hมีการใช้งานในlibc.so(หรือlibc.aสำหรับการเชื่อมโยงแบบคงที่) ซึ่งเชื่อมโยงไปยังปฏิบัติการของคุณโดยค่าเริ่มต้น (ราวกับว่า-lcมีการระบุ) สามารถสั่ง GCC เพื่อหลีกเลี่ยงการเชื่อมโยงอัตโนมัตินี้ด้วย-nostdlibหรือ-nodefaultlibsตัวเลือก

ฟังก์ชั่นทางคณิตศาสตร์ในmath.hมีการใช้งานในlibm.so(หรือlibm.aสำหรับการเชื่อมโยงแบบคงที่) และlibmไม่ได้เชื่อมโยงโดยค่าเริ่มต้น มีเหตุผลทางประวัติศาสตร์สำหรับเรื่องนี้libm/ libcแตกไม่มีใครน่าเชื่อถือมาก

น่าสนใจ C ++ runtime libstdc++จำเป็นต้องใช้libmดังนั้นหากคุณรวบรวมโปรแกรม C ++ กับ GCC ( g++) คุณจะได้รับการlibmเชื่อมโยงโดยอัตโนมัติ


8
สิ่งนี้ไม่เกี่ยวข้องกับ Linux เนื่องจากเป็นเรื่องปกติมานานกว่า Linux ฉันสงสัยว่ามันมีบางอย่างเกี่ยวข้องกับการพยายามลดขนาดไฟล์ที่สามารถเรียกใช้งานได้เนื่องจากมีโปรแกรมจำนวนมากที่ไม่ต้องการฟังก์ชันทางคณิตศาสตร์
David Thornley

39
บนระบบโบราณถ้าฟังก์ชันทางคณิตศาสตร์มีอยู่ใน libc จากนั้นการรวบรวมโปรแกรมทั้งหมดจะช้าลงเอ็กซีคิวต์เอาต์พุตจะมีขนาดใหญ่ขึ้นและรันไทม์จะต้องใช้หน่วยความจำมากขึ้นโดยไม่มีประโยชน์กับโปรแกรมส่วนใหญ่ที่ไม่ใช้ฟังก์ชันคณิตศาสตร์เหล่านี้เลย ทุกวันนี้เรามีการสนับสนุนที่ดีสำหรับไลบรารีที่ใช้ร่วมกันและแม้ในขณะที่การเชื่อมโยงแบบคงที่ แต่ก็มีการตั้งค่าไลบรารีมาตรฐานเพื่อให้รหัสที่ไม่ได้ใช้สามารถถูกละทิ้งได้ดังนั้นจึงไม่มีเหตุผลที่ดีอีกต่อไป
ephemient

38
@ephemient แม้ในอดีตการเชื่อมโยงไปยังไลบรารีไม่ได้ดึงเนื้อหาทั้งหมดของไลบรารีไปยังไฟล์ที่เรียกใช้งานได้ ตัวเชื่อมโยงแม้เป็นเทคโนโลยีที่มักถูกมองข้าม แต่ก็มีประสิทธิภาพในอดีต

7
@ephemient นอกจากนี้ยังมีห้องสมุดสาธารณะที่ใช้ร่วมกันมานานกว่าที่คุณคิด พวกเขาถูกประดิษฐ์ขึ้นในปี 1950 ไม่ใช่ 1980

5
ฉันคิดว่าในตอนท้ายของวันสิ่งที่เรากำลังดูอยู่นั้นไม่มีอะไรมากไปกว่าการอนุรักษ์แบบ GCC: "มันใช้งานได้ทุกอย่าง" ฉันหวังว่าพวกเขาจะใช้เหตุผลเดียวกันกับส่วนขยายคอมไพเลอร์ของพวกเขา

77

โปรดจำไว้ว่า C เป็นภาษาเก่าและ FPU นั้นเป็นปรากฏการณ์ที่ค่อนข้างเร็ว ฉันเห็น C เป็นครั้งแรกในโปรเซสเซอร์ 8 บิตซึ่งเป็นงานที่ต้องทำเลขคณิตจำนวนเต็ม 32 บิต การใช้งานเหล่านี้จำนวนมากไม่ได้มีห้องสมุดคณิตศาสตร์แบบอิงดัชนี!

แม้แต่บนเครื่อง 68000 เครื่องแรก (Mac, Atari ST, Amiga) โปรเซสเซอร์ร่วมจุดลอยตัวมักเป็นอุปกรณ์เสริมที่มีราคาแพง

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

มีการแลกเปลี่ยนกันมาเป็นเวลานาน บางครั้งมีแพ็คเกจคณิตศาสตร์ที่เรียกว่า "fastmath" หรือแบบนั้น ทางออกที่ดีที่สุดสำหรับคณิตศาสตร์คืออะไร? สิ่งที่ถูกต้อง แต่ช้าจริงๆเหรอ? ไม่ถูกต้อง แต่เร็วหรือไม่ ตารางใหญ่สำหรับฟังก์ชั่นตรีโกณฯ ? มันไม่ได้จนกว่าตัวประมวลผลร่วมจะรับประกันว่าจะอยู่ในคอมพิวเตอร์ที่การใช้งานส่วนใหญ่เห็นได้ชัด ฉันคิดว่ามีโปรแกรมเมอร์บางคนอยู่ที่นั่นตอนนี้ทำงานบนชิปฝังตัวพยายามที่จะตัดสินใจว่าจะนำห้องสมุดคณิตศาสตร์เพื่อจัดการกับปัญหาคณิตศาสตร์บางอย่างหรือไม่

นั่นเป็นเหตุผลทางคณิตศาสตร์ที่ไม่ได้มาตรฐาน โปรแกรมส่วนใหญ่หรืออาจส่วนใหญ่ไม่ได้ใช้โฟลว์เดียว ถ้า FPUs อยู่ใกล้ ๆ และลอยตัวและคู่ถูกเสมอเพื่อให้ทำงานไม่ต้องสงสัยเลยว่าจะมี "stdmath"


เฮ้ฉันใช้ Pade Approap สำหรับ (1 + x) ^ y ใน Java ในเดสก์ท็อปพีซี Log, exp และ pow ยังช้าอยู่
quant_dev

จุดดี. และฉันเห็นการประมาณค่า sin () ในปลั๊กอินเสียง
Nosredna

11
สิ่งนี้อธิบายได้ว่าทำไมlibmไม่เชื่อมโยงโดยค่าเริ่มต้น แต่คณิตศาสตร์เป็นมาตรฐานจาก C89 และก่อนหน้านั้น K&R มีมาตรฐานจริงดังนั้นคำพูด "stdmath" ของคุณจึงไม่สมเหตุสมผล
Fred Foo

@FredFoo ประเภทและอินเทอร์เฟซเป็นมาตรฐาน แต่ไม่ใช่การนำไปใช้ ฉันคิดว่า Nosredna อ้างถึงห้องสมุดคณิตศาสตร์มาตรฐาน
ทิมเบิร์ด

72

เนื่องจากการฝึกฝนทางประวัติศาสตร์ที่น่าหัวเราะที่ไม่มีใครเต็มใจแก้ไข การรวมฟังก์ชั่นทั้งหมดที่ต้องการโดย C และ POSIX ลงในไฟล์ไลบรารีเดียวไม่เพียง แต่จะหลีกเลี่ยงคำถามนี้ที่ถูกถามซ้ำแล้วซ้ำอีก แต่ยังช่วยประหยัดเวลาและหน่วยความจำจำนวนมากเมื่อเชื่อมโยงแบบไดนามิกเนื่องจากแต่ละ.soไฟล์ที่เชื่อมโยง เพื่อค้นหาและค้นหาและสองสามหน้าสำหรับตัวแปรสแตติกการเปลี่ยนตำแหน่ง ฯลฯ

การดำเนินการที่ฟังก์ชั่นทั้งหมดที่มีในห้องสมุดและ-lm, -lpthread, -lrtฯลฯ ตัวเลือกที่มีอยู่ทั้งหมดไม่มี Ops (หรือเชื่อมโยงไปยังที่ว่างเปล่า.aไฟล์) เป็นอย่างดี POSIX สอดคล้องและดีกว่าอย่างแน่นอน

หมายเหตุ: ฉันกำลังพูดถึง POSIX เพราะ C เองไม่ได้ระบุอะไรเกี่ยวกับวิธีเรียกใช้คอมไพเลอร์ ดังนั้นคุณสามารถถือว่าgcc -std=c99 -lmเป็นวิธีการใช้งานเฉพาะที่คอมไพเลอร์จะต้องเรียกใช้สำหรับพฤติกรรมที่สอดคล้อง


9
+1 สำหรับการชี้ให้เห็นว่า POSIX ไม่ต้องการไลบรารี libm, libc และ librt ที่แยกจากกัน ตัวอย่างเช่นบน Mac OS ทุกอย่างอยู่ใน libSystem เดียว (ซึ่งรวมถึง libdbm, libdl, libgcc_s, libinfo, libm, libpoll, libproc และ librpcsvc)
F'x

3
–1 สำหรับการเก็งกำไรเกี่ยวกับการค้นหาไลบรารีส่งผลกระทบต่อประสิทธิภาพโดยไม่ต้องสำรองข้อมูลด้วยลิงก์หรือตัวเลข "โปรไฟล์. อย่าคาดเดา"
F'x

12
นี่ไม่ใช่การเก็งกำไร ฉันไม่มีเอกสารที่ตีพิมพ์ แต่ฉันได้ทำการวัดทั้งหมดด้วยตัวเองและความแตกต่างนั้นใหญ่มาก เพียงใช้straceกับหนึ่งในตัวเลือกช่วงเวลาเพื่อดูว่าใช้เวลาเริ่มต้นเท่าไรในการลิงก์แบบไดนามิกหรือเปรียบเทียบการทำงาน./configureบนระบบที่ยูทิลิตี้มาตรฐานทั้งหมดเชื่อมโยงแบบคงที่และแบบที่ลิงค์แบบไดนามิก แม้แต่นักพัฒนาแอพเดสก์ท็อปหลักและผู้รวมระบบก็ยังตระหนักถึงต้นทุนของการเชื่อมโยงแบบไดนามิก นี่คือเหตุผลที่มีสิ่งต่าง ๆ เช่น prelink ฉันแน่ใจว่าคุณสามารถหามาตรฐานในเอกสารเหล่านี้บางส่วน
. GitHub หยุดช่วยน้ำแข็ง

1
โปรดทราบว่า POSIX ไม่จำเป็นต้อง-lmได้รับการยอมรับและการใช้งานที่ใช้อินเตอร์เฟซคณิตศาสตร์ต้องใช้-lmแต่ก็สามารถเป็นตัวเลือกภายในการจัดการ (หรือแม้กระทั่งไม่สนใจ) โดยคำสั่งคอมไพเลอร์ไม่ได้เป็นไฟล์ไลบรารีที่เกิดขึ้นจริง หรืออาจเป็น.aไฟล์ว่างเปล่าหากอินเตอร์เฟสอยู่ใน libc หลัก
. GitHub หยุดช่วยน้ำแข็ง

6
@FX: ไม่รู้ว่าทำไมฉันถึงลืมเรื่องนี้มาก่อน: strace -ttจะแสดงเวลาที่ใช้ในการลิงก์แบบไดนามิกได้อย่างง่ายดาย มันไม่สวย และบน Linux การตรวจสอบ/proc/sys/smapsจะแสดงโอเวอร์เฮดหน่วยความจำของไลบรารีเพิ่มเติม
. GitHub หยุดช่วยน้ำแข็ง

33

เพราะtime()และมีฟังก์ชั่นอื่น ๆ ที่builtinกำหนดไว้ในไลบรารี C ( libc) เองและ GCC จะเชื่อมโยงไปยัง libc เสมอเว้นแต่คุณจะใช้-ffreestandingตัวเลือกการคอมไพล์ อย่างไรก็ตามฟังก์ชั่นทางคณิตศาสตร์อาศัยอยู่ในlibmซึ่งไม่ได้เชื่อมโยงโดยนัยโดย gcc


8
บน LLVM gcc ฉันไม่ต้องเพิ่ม -lm ทำไมนี้
bot47

26

คำอธิบายให้ไว้ที่นี่ :

ดังนั้นหากโปรแกรมของคุณใช้ฟังก์ชั่นคณิตศาสตร์และรวมไปถึงmath.hคุณจะต้องเชื่อมโยงห้องสมุดคณิตศาสตร์อย่างชัดเจนด้วยการส่ง-lmค่าสถานะ เหตุผลสำหรับการแยกโดยเฉพาะนี้คือนักคณิตศาสตร์มีความพิถีพิถันมากเกี่ยวกับวิธีการคำนวณทางคณิตศาสตร์ของพวกเขาและพวกเขาอาจต้องการใช้การใช้งานฟังก์ชันคณิตศาสตร์แทนการใช้มาตรฐาน หากฟังก์ชั่นทางคณิตศาสตร์ถูกรวบรวมเข้ามาlibc.aมันจะไม่สามารถทำเช่นนั้นได้

[แก้ไข]

ฉันไม่แน่ใจว่าฉันเห็นด้วยกับเรื่องนี้ ถ้าคุณมีไลบรารี่ที่ให้พูดsqrt()และส่งต่อไปยังไลบรารี่มาตรฐานตัวลิงก์ Unix จะใช้เวอร์ชันของคุณใช่ไหม


10
ฉันไม่คิดว่าจะรับประกันได้ว่าจะเกิดขึ้น คุณอาจท้ายด้วยความขัดแย้งสัญลักษณ์แทน มันอาจจะขึ้นอยู่กับ linker และรูปแบบของห้องสมุด ฉันยังพบว่าเหตุผลนั้นอ่อนแอ ถ้าคุณกำลังทำฟังก์ชัน sqrt ที่กำหนดเองคุณมันไม่ควรจะให้มันชื่อเดียวกับฟังก์ชั่นมาตรฐาน sqrt ถึงแม้ว่ามันจะเป็นสิ่งเดียวกัน ...
ephemient

1
อันที่จริงการทำให้ฟังก์ชั่นของคุณเอง (ไม่คงที่) ชื่อsqrtผลลัพธ์ในโปรแกรมที่มีพฤติกรรมที่ไม่ได้กำหนด
. GitHub หยุดช่วยน้ำแข็ง

@Bastien ค้นหาที่ดี และเมื่อมาถึงจุดของคุณคุณหมายถึงอะไร "ก่อนไลบรารีมาตรฐาน" ฉันคิดว่าไลบรารีมาตรฐานมีการเชื่อมโยงโดยค่าเริ่มต้นและไม่จำเป็นต้องเชื่อมโยงผ่านตัวเลือกบรรทัดคำสั่ง ดังนั้นไลบรารีมาตรฐานจะเป็นตัวแรกสำหรับตัวลิงก์และตัวหนึ่งไม่สามารถทำการปรับใช้ของตัวเอง "ก่อนไลบรารีมาตรฐาน"
Rocky Inde

@RockyInde: ดูคำตอบของฉันฉันคิดว่าฉันหมายถึง "ก่อนห้องสมุดคณิตศาสตร์มาตรฐาน" แต่ฉันคิดว่ามีตัวเลือกคอมไพเลอร์ที่จะไม่เชื่อมโยงไลบรารี C มาตรฐานซึ่งจะช่วยให้คุณสามารถส่งผ่านของคุณได้
Bastien Léonard

@ BastienLéonardฉันใช้ gcc รุ่น 7.2 ซึ่ง-lmเป็นตัวเลือกทั้งหมด ความคิดใด ๆ
Donghua Liu

5

มีการอภิปรายอย่างละเอียดของการเชื่อมโยงไปยังห้องสมุดภายนอกในเรื่องรู้เบื้องต้นเกี่ยวกับ GCC - การเชื่อมโยงกับห้องสมุดภายนอก หากไลบรารีเป็นสมาชิกของไลบรารีมาตรฐาน (เช่น stdio) คุณไม่จำเป็นต้องระบุให้คอมไพเลอร์ (เป็นตัวเชื่อมโยง) เพื่อเชื่อมโยง

แก้ไข: หลังจากอ่านคำตอบและความคิดเห็นอื่น ๆ แล้วฉันคิดว่าการอ้างอิง libc.aและการอ้างอิง libm ที่ลิงก์ไปยังทั้งคู่มีจำนวนมากที่จะพูดเกี่ยวกับสาเหตุที่ทั้งสองแยกจากกัน

โปรดทราบว่าฟังก์ชั่นจำนวนมากใน 'libm.a' (ห้องสมุดคณิตศาสตร์) มีการกำหนดไว้ใน 'math.h' แต่ไม่มีใน libc.a บางตัวอาจจะสับสน แต่กฎของ thumb คือสิ่งนี้ - ไลบรารี C ประกอบด้วยฟังก์ชันเหล่านั้นที่ ANSI สั่งการต้องมีอยู่ดังนั้นคุณไม่จำเป็นต้องใช้ -lm หากคุณใช้ฟังก์ชัน ANSI เท่านั้น ในทางตรงกันข้าม `libm.a 'มีฟังก์ชั่นมากขึ้นและรองรับฟังก์ชั่นเพิ่มเติมเช่นการเรียกกลับ matherr และการปฏิบัติตามมาตรฐานทางเลือกหลายประการของพฤติกรรมในกรณีที่เกิดข้อผิดพลาด FP ดูส่วน libm สำหรับรายละเอียดเพิ่มเติม


1
ซึ่งไม่ตอบคำถามที่ว่าทำไมคุณถึงต้องเชื่อมโยงในไลบรารีการจับคู่แยกต่างหาก เห็นได้ชัดว่าคุณต้องการเชื่อมโยงห้องสมุด OpenGL แยกจากกัน แต่เนื้อหาคณิตศาสตร์โดยทั่วไปมีประโยชน์
David Thornley

@ David: ใช่คุณ มันไม่ชัดเจนสำหรับฉันจากคำถามที่ว่านี่เป็นบิตที่ OP ถาม ฉันแก้ไขคำตอบตามที่คุณแสดงความคิดเห็น
Bill the Lizard

ฉันรู้ว่าฉันมีเหตุผลที่รวบรวมโปรแกรมที่ใช้ฟังก์ชั่นและการทำงานโดยไม่รวมถึงห้องสมุดผ่านsqrt -lmขอบคุณ!
L_K

5

ดังที่ ephemient กล่าวว่าไลบรารี C libc เชื่อมโยงกันโดยค่าเริ่มต้นและไลบรารีนี้มีการใช้งานของ stdlib.h, stdio.h และไฟล์ส่วนหัวมาตรฐานอื่น ๆ อีกหลายรายการ เพียงเพิ่มไปยังมันตาม " คำแนะนำเพื่อ GCC " คำสั่ง linker สำหรับโปรแกรม "Hello World" พื้นฐานใน C เป็นดังนี้:

ld -dynamic-linker /lib/ld-linux.so.2 /usr/lib/crt1.o 
/usr/lib/crti.o /usr/libgcc-lib /i686/3.3.1/crtbegin.o
-L/usr/lib/gcc-lib/i686/3.3.1 hello.o -lgcc -lgcc_eh -lc 
-lgcc -lgcc_eh /usr/lib/gcc-lib/i686/3.3.1/crtend.o /usr/lib/crtn.o

สังเกตเห็นตัวเลือก-lcในบรรทัดที่สามที่เชื่อมโยงไลบรารี C


3

ฉันคิดว่ามันเป็นเรื่องโดยพลการ คุณต้องลากเส้นที่ไหนสักแห่ง (ไลบรารีใดเป็นค่าเริ่มต้นและต้องระบุ)

มันให้โอกาสคุณในการแทนที่ด้วยอันที่ต่างกันซึ่งมีฟังก์ชั่นเหมือนกัน แต่ฉันไม่คิดว่ามันจะเป็นเรื่องธรรมดา

แก้ไข: (จากความเห็นของฉันเอง): ฉันคิดว่า gcc ทำเช่นนี้เพื่อรักษาความเข้ากันได้ย้อนหลังกับสำเนาต้นฉบับ ฉันเดาว่าทำไมซีซีถึงเกิดขึ้นเพราะเวลาในการสร้าง - ซีซีเขียนขึ้นสำหรับเครื่องจักรที่ใช้พลังงานน้อยกว่าที่เรามีอยู่ตอนนี้ โปรแกรมจำนวนมากไม่มีคณิตศาสตร์แบบอิงดัชนีและพวกเขาอาจใช้ไลบรารีทั้งหมดที่ไม่ได้ใช้เป็นค่าเริ่มต้น ฉันเดาว่าเวลาในการสร้างของ UNIX OS และเครื่องมือที่สอดคล้องกับมันเป็นแรงผลักดัน


ฉันคิดว่าความคิดที่อยู่เบื้องหลังคำถามคือเนื้อหาของ libm เป็นส่วนใหญ่ของไลบรารี C มาตรฐานทำไมพวกเขาถึงไม่ใช้ libc
Evan Teran

1
เหตุผลที่ gcc คือการรักษาความเข้ากันได้กับซีซีดั้งเดิมใน AT&T Unix ฉันใช้ 3B2 ในปี 1988 และคุณต้องใช้ -lm เพื่อให้ได้คณิตศาสตร์ ดูเหมือนว่าฉันจะไม่มีข้อ จำกัด ในเวลานั้น ใน Visual Studio ฉันจำไม่ได้ว่าต้องเพิ่มคณิตศาสตร์ แต่คุณต้องเพิ่มไลบรารี c-runtime อื่น ๆ ที่ดูเหมือน ฉันคิดว่าผู้ขายคอมไพเลอร์มีเหตุผล (build time?) แต่ตอนนี้ฉันพนันได้เลยว่า gcc กำลังพยายามเข้ากันได้ย้อนหลัง
Lou Franco

3

หากฉันใส่ stdlib.h หรือ stdio.h ฉันไม่จำเป็นต้องเชื่อมโยงสิ่งเหล่านั้น แต่ฉันต้องเชื่อมโยงเมื่อฉันคอมไพล์:

stdlib.h, stdio.hเป็นไฟล์ส่วนหัว คุณรวมไว้เพื่อความสะดวกของคุณ พวกเขาคาดการณ์ว่าจะมีสัญลักษณ์ใดบ้างที่จะเชื่อมโยงกับคุณในห้องสมุดที่เหมาะสม การใช้งานอยู่ในไฟล์ไลบรารีซึ่งเป็นที่ที่ฟังก์ชั่นใช้งานได้จริง

การรวมmath.hเป็นเพียงขั้นตอนแรกในการเข้าถึงฟังก์ชั่นคณิตศาสตร์ทั้งหมด

นอกจากนี้คุณไม่ต้องเชื่อมโยงกับlibmถ้าคุณไม่ได้ใช้ฟังก์ชั่นของมันแม้ว่าคุณจะทำ#include <math.h>ขั้นตอนที่เป็นข้อมูลสำหรับคุณสำหรับคอมไพเลอร์เกี่ยวกับสัญลักษณ์

stdlib.h, stdio.hอ้างถึงฟังก์ชั่นในการใช้ได้libcที่เกิดขึ้นจะเชื่อมโยงเสมอเพื่อให้ผู้ใช้ไม่ต้องทำมันเอง


2

stdio เป็นส่วนหนึ่งของไลบรารี C มาตรฐานซึ่งโดยค่าเริ่มต้น gcc จะเชื่อมโยงกับ

การใช้งานฟังก์ชั่นทางคณิตศาสตร์อยู่ในไฟล์ libm แยกต่างหากที่ไม่ได้เชื่อมโยงโดยค่าเริ่มต้นดังนั้นคุณต้องระบุ -lm ยังไม่มีความสัมพันธ์ระหว่างไฟล์ส่วนหัวและไฟล์ไลบรารีเหล่านั้น


3
เขารู้ว่า .. เขากำลังถามว่าทำไม
Evan Teran

เขาบอกว่าทำไม Simon อธิบายว่าห้องสมุดบางแห่งมีการเชื่อมโยงโดยค่าเริ่มต้นเช่น stdio ในขณะที่ห้องสมุดคณิตศาสตร์ไม่ได้เชื่อมโยงโดยค่าเริ่มต้นดังนั้นจึงต้องมีการระบุ
mnuzzo

5
ฉันจะบอกว่าลักษณะของคำถามคือการถามว่าทำไม libm ไม่เชื่อมโยงโดยค่าเริ่มต้น (หรือแยกจาก libc) เนื่องจากเนื้อหาส่วนใหญ่เป็นส่วนหนึ่งของไลบรารีมาตรฐาน c
Evan Teran

2

ฉันเดาว่ามันเป็นวิธีที่จะทำให้แอพที่ไม่ได้ใช้งานเลยทำงานได้ดีขึ้นเล็กน้อย นี่คือความคิดของฉันเกี่ยวกับเรื่องนี้

x86 OSes (และฉันนึกภาพคนอื่น ๆ ) จำเป็นต้องเก็บสถานะ FPU ไว้ที่ context switch อย่างไรก็ตามระบบปฏิบัติการส่วนใหญ่มักจะรำคาญที่จะบันทึก / กู้คืนสถานะนี้หลังจากที่แอปพยายามใช้ FPU เป็นครั้งแรก

นอกจากนี้อาจมีรหัสพื้นฐานบางอย่างในไลบรารีคณิตศาสตร์ซึ่งจะตั้งค่า FPU ให้เป็นสถานะฐานสติเมื่อโหลดไลบรารี

ดังนั้นหากคุณไม่เชื่อมโยงในโค้ดคณิตศาสตร์ใด ๆ เลยสิ่งนี้จะไม่เกิดขึ้นดังนั้นระบบปฏิบัติการไม่จำเป็นต้องบันทึก / กู้คืนสถานะ FPU ใด ๆ เลยทำให้การสลับบริบทมีประสิทธิภาพมากขึ้นเล็กน้อย

เพียงแค่เดาว่า

แก้ไข:ในการตอบสนองต่อความคิดเห็นบางส่วนหลักฐานพื้นฐานเดียวกันยังคงใช้กับกรณีที่ไม่ใช่ FPU (หลักฐานยืนยันว่าเป็นการสร้างแอปที่ไม่ทำให้การใช้ libm ทำงานได้ดีขึ้นเล็กน้อย)

ตัวอย่างเช่นหากมี soft-FPU ซึ่งเป็น likley ในช่วงต้นของ C จากนั้นการแยก libm สามารถป้องกันโค้ดขนาดใหญ่ (และช้าถ้าใช้) จากการเชื่อมโยงโดยไม่จำเป็น

นอกจากนี้หากมีการเชื่อมโยงแบบสแตติกพร้อมใช้งานเท่านั้นอาร์กิวเมนต์ที่คล้ายกันจะมีผลบังคับใช้ซึ่งจะทำให้ขนาดที่สามารถเรียกใช้งานได้และเวลาการคอมไพล์ลดลง


หากคุณไม่ได้เชื่อมโยงกับ libm แต่ให้แตะ x87 FPU ด้วยวิธีการอื่น (เช่นการดำเนินการกับการลอย) เคอร์เนล x86 ไม่จำเป็นต้องบันทึกสถานะ FPU ผมไม่คิดว่านี่คือการคาดเดาที่ดีมาก ...
ephemient

แน่นอนถ้าคุณใช้ FPU ด้วยตนเองเคอร์เนลจะยังคงต้องบันทึก / กู้คืนสถานะของมัน ฉันกำลังบอกว่าถ้าคุณไม่เคยใช้ (รวมถึงไม่ใช้ libm) ก็ไม่จำเป็นต้อง
Evan Teran

จริงๆแล้วมันสามารถขึ้นอยู่กับเคอร์เนลได้อย่างมาก ไลบรารีคณิตศาสตร์ที่เคอร์เนลใช้อาจมีฟังก์ชั่น save_FPU_on_switch () ที่เปิดใช้งานในขณะที่คนอื่น ๆ ตรวจพบว่ามีการแตะ FPU หรือไม่
Earlz

1
หากฉันจำได้อย่างถูกต้องปัญหาทั้งหมดจะมาก่อนตัวประมวลผลร่วมจุดลอยตัวแม้จะอยู่ในไมโครโปรเซสเซอร์
Nosredna

@earlz: วิธีการมีการบันทึกคำขอห้องสมุดคณิตศาสตร์จะเป็นการออกแบบที่แย่ ถ้าพวกเขาใช้ FPU ด้วยวิธีอื่น วิธีการที่มีเหตุผลอย่างเดียว (นอกเหนือจากการบันทึก / เรียกคืนเสมอ) คือการตรวจสอบการใช้งานและจากนั้นเริ่มบันทึก / เรียกคืน
Evan Teran
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.