ควรใช้ไลบรารีแบบไดนามิกและแบบคงที่เมื่อใด


437

เมื่อสร้างไลบรารีคลาสใน C ++ คุณสามารถเลือกระหว่างไลบรารี dynamic ( .dll, .so) และ static ( .lib, .a) อะไรคือความแตกต่างระหว่างพวกเขาและเมื่อใดที่เหมาะสมที่จะใช้


2
ควรสังเกตว่ามีบางสิ่งที่เรียกว่า "นำเข้าไลบรารี" ตรวจสอบstackoverflow.com/questions/3573475/ …
Wakan Tanka

คำตอบ:


299

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

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

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

ไลบรารีแบบไดนามิกได้รับการพิจารณาว่าเป็นวิธีที่ดีกว่าโดยส่วนใหญ่ แต่เดิมแล้วพวกเขามีข้อบกพร่องที่สำคัญ (นรกของ Google DLL) ซึ่งมีทั้งหมด แต่ถูกกำจัดโดยระบบปฏิบัติการ Windows รุ่นล่าสุด (โดยเฉพาะ Windows XP)


71
บน Windows / Mac (ไม่มีตัวจัดการแพ็คเกจ) ไม่มีเหตุผลที่ดีในการใช้ไลบรารีแบบไดนามิกบนสแตติก เนื่องจาก Windows DLL ไม่สามารถเปลี่ยนตำแหน่งได้การใช้รหัสร่วมกันจึงไม่สามารถใช้งานได้ ประโยชน์ที่แท้จริงเท่านั้นคือการอัปเดตห้องสมุดง่ายขึ้น
Zifre

5
สำหรับ Mac ฉันใช้ไลบรารีแบบไดนามิกจำนวนมาก ตัวอย่างเช่น mac os x ได้ฝัง sqlite3 ฉันสร้างโปรแกรมที่มีคุณสมบัติฐานข้อมูล sqlite3 สำหรับการจัดเก็บประสิทธิภาพ อย่างไรก็ตามเนื่องจากมันไม่ค่อยมีการใช้การเชื่อมโยงแบบไดนามิกที่ประหยัดเวลาในการรวบรวมทำให้การทดสอบง่ายขึ้น / เร็วขึ้น แต่ถ้าฉันจะสร้างรุ่นที่วางจำหน่ายฉันคิดว่าฉันจะใช้ไลบรารีแบบคงที่เสมอในกรณีที่ปัญหาความเข้ากัน
ReachConnection

6
@Zifre: relocatable = สามารถโหลดได้ที่ที่อยู่เสมือนที่แตกต่างกัน DLL รองรับสิ่งนี้อย่างแน่นอน
dma_k

20
@dma_k: Windows DLL สามารถโหลดได้ที่ที่อยู่ต่างกัน แต่เพียงเพราะ linker คัดลอกรหัสทั้งหมดและเปลี่ยนหมายเลขที่อยู่ ด้วยออบเจ็กต์ที่ใช้ร่วมกันการอ้างอิงที่อยู่ทั้งหมดนั้นสัมพันธ์กันดังนั้นหลาย ๆ กระบวนการสามารถแชร์หน่วยความจำเดียวกันสำหรับออบเจ็กต์ที่แชร์ ในคำอื่น ๆ บน Windows, A 1 MB DLL ที่ใช้โดย 3 โปรแกรม = 3 MB บน Linux A MB SO ใช้โดย 3 โปรแกรม = 1 MB
Zifre

7
ทั้ง Windows และ Linux มีแนวคิดของการย้ายตำแหน่งโหลด -ttete ของ shared library eli.thegreenplace.net/2011/08/25/ ...... สิ่งที่ยิ่งใหญ่ที่สุดที่อนุญาตให้ Position Independent Code ไม่ใช่สิ่งที่พิเศษสำหรับ Linux แทนที่จะเพิ่มที่อยู่แบบสัมพันธ์กับ RIP พร้อมชุดคำสั่ง x64; ทั้ง Windows และ Linux สามารถใช้ประโยชน์จากการกำหนดแอดเดรสแบบสัมพันธ์ของ RIP จะลดจำนวนโปรแกรมแก้ไขเมื่อทำการย้ายไลบรารี
clemahieu

194

คนอื่น ๆ ได้อธิบายอย่างเพียงพอว่าห้องสมุดแบบสแตติกคืออะไร แต่ฉันต้องการชี้ให้เห็นบางส่วนของการใช้ห้องสมุดแบบคงที่อย่างน้อยใน Windows:

  • Singletons:หากมีบางสิ่งที่จำเป็นต้องเป็นโกลบอล / สแตติกและไม่ซ้ำกันให้ระมัดระวังในการวางไว้ในไลบรารี่แบบคงที่ หาก DLLs หลายตัวเชื่อมโยงกับไลบรารี่คงที่พวกเขาแต่ละคนจะได้รับสำเนาซิงเกิลของตนเอง อย่างไรก็ตามหากแอปพลิเคชันของคุณเป็น EXE เดียวโดยไม่มี DLLs ที่กำหนดเองนี่อาจไม่เป็นปัญหา

  • การลบรหัสที่ไม่ได้อ้างถึง:เมื่อคุณเชื่อมโยงกับไลบรารีคงที่เฉพาะส่วนต่าง ๆ ของไลบรารีแบบคงที่ที่อ้างถึงโดย DLL / EXE ของคุณจะได้รับการเชื่อมโยงเข้ากับ DLL / EXE ของคุณ

    ตัวอย่างเช่นถ้าmylib.libมีa.objและb.objและ DLL / EXE ของคุณอ้างอิงเฉพาะฟังก์ชั่นหรือตัวแปรจากa.objทั้งหมดb.objจะถูกยกเลิกโดย linker หากb.objมีวัตถุทั่วโลก / คงที่คอนสตรัคและ destructors ของพวกเขาจะไม่ได้รับการดำเนินการ หากคอนสตรัคเตอร์ / อุปกรณ์ทำลายเหล่านั้นมีผลข้างเคียงคุณอาจผิดหวังหากไม่มี

    ในทำนองเดียวกันหากไลบรารีแบบสแตติกมีจุดเข้าใช้งานพิเศษคุณอาจต้องดูแลว่ามีการรวมไว้จริง ๆ ตัวอย่างของสิ่งนี้ในการเขียนโปรแกรมแบบฝังตัว (โอเคไม่ใช่ Windows) จะเป็นตัวจัดการขัดจังหวะที่ถูกทำเครื่องหมายว่าเป็นที่อยู่เฉพาะ คุณต้องทำเครื่องหมายตัวจัดการขัดจังหวะเป็นจุดเริ่มต้นเพื่อให้แน่ใจว่าไม่ได้ถูกยกเลิก

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

  • สัญลักษณ์แก้จุดบกพร่อง:คุณอาจต้องการ PDB แยกต่างหากสำหรับแต่ละไลบรารีคงที่หรือคุณอาจต้องการวางสัญลักษณ์แก้จุดบกพร่องในไฟล์วัตถุเพื่อให้พวกเขาได้รับการรีดลงใน PDB สำหรับ DLL / EXE เอกสาร Visual C ++ อธิบายตัวเลือกที่จำเป็น

  • RTTI:คุณอาจลงท้ายด้วยtype_infoวัตถุหลายรายการสำหรับคลาสเดียวกันถ้าคุณเชื่อมโยงไลบรารีแบบคงที่เดียวลงใน DLLs หลายตัว หากโปรแกรมของคุณสันนิษฐานว่าtype_infoเป็นข้อมูล "ซิงเกิล" และใช้งาน&typeid()หรือtype_info::before()คุณอาจได้ผลลัพธ์ที่ไม่พึงประสงค์และน่าประหลาดใจ


23
สำหรับประเด็นเกี่ยวกับ singletons อย่าลืมว่า DLL อาจถูกโหลดหลายครั้ง (รุ่นเดียวกันหรือรุ่น mulitple) และยังไม่มีการรับประกันแบบซิงเกิล
นายพราน Adrian

จุดเพิ่มเติมเกี่ยวกับการลบรหัสที่ไม่ได้รับการอ้างอิง: การโทรไปยัง DLLs นั้นจำเป็นต้องมีการโทรจริงเพื่อบังคับให้โหลด DLL อ้างอิง การเพิ่มมันเป็นข้อมูลอ้างอิง แต่ไม่รวมถึงการโทรใด ๆ ที่การอ้างอิงนั้นจะยังคงได้รับผลลัพธ์เช่นเดียวกับการมี libary แบบคงที่ซึ่งไม่เรียกสิ่งใด ความแตกต่างเพียงอย่างเดียวคือสิ่งที่จัดส่งจริง ในทั้งสองกรณีตัวสร้างแบบคงที่และตัวทำลายจะไม่ยิง
Orion Adrian

@ bk1e นั่นไม่ควรเกิดขึ้น .a จะมีสัญลักษณ์ทั้งหมดที่สร้างขึ้นด้วยเสมอ เมื่อเชื่อมโยงกับแอปพลิเคชันของคุณแบบสแตติกใช่เฉพาะสัญลักษณ์ที่ใช้จะถูกเชื่อมโยง
Miles Rout

62

lib คือหน่วยของรหัสที่รวมอยู่ในโปรแกรมของคุณ

dll เป็นหน่วยประมวลผลแบบสแตนด์อโลนของรหัส มันถูกโหลดในกระบวนการก็ต่อเมื่อมีการโทรเข้าไปในรหัสนั้น dll สามารถใช้งานได้หลายแอพพลิเคชั่นและโหลดในหลาย ๆ กระบวนการในขณะที่ยังคงมีรหัสอยู่เพียงหนึ่งสำเนาในฮาร์ดไดรฟ์

ข้อดี dll : สามารถใช้ซ้ำ / แบ่งปันรหัสระหว่างผลิตภัณฑ์ต่าง ๆ ; โหลดในหน่วยความจำกระบวนการตามความต้องการและสามารถยกเลิกการโหลดเมื่อไม่ต้องการ; สามารถอัปเกรดเป็นอิสระจากส่วนที่เหลือของโปรแกรม

ข้อเสีย dll : ผลกระทบต่อประสิทธิภาพของการโหลด dll และการรีบูตรหัส; ปัญหาการกำหนดเวอร์ชัน ("dll Hell")

ข้อดีของ Lib : ไม่มีผลกระทบต่อประสิทธิภาพเนื่องจากมีการโหลดรหัสในกระบวนการเสมอและไม่ได้ถูกลดระดับ ไม่มีปัญหาการกำหนดเวอร์ชัน

Lib ข้อเสีย : ปฏิบัติการ / กระบวนการ "ขยาย" - รหัสทั้งหมดอยู่ในปฏิบัติการของคุณและโหลดเมื่อเริ่มกระบวนการ; ไม่มีการใช้ซ้ำ / ใช้ร่วมกัน - ผลิตภัณฑ์แต่ละชนิดมีรหัสของตนเอง


การรีบูตยังสามารถทำได้ในเวลาบิลด์โดยใช้ rebase.exe หรือผ่านตัวเลือก / BASE ไปยัง link.exe การดำเนินการนี้มีประสิทธิภาพหรือไม่ขึ้นอยู่กับว่ามีข้อขัดแย้งของพื้นที่ที่อยู่ที่ไม่คาดคิดเกิดขึ้นขณะใช้งานจริงหรือไม่
bk1e

24

นอกจากนี้ผลกระทบทางเทคนิคของคงเทียบกับห้องสมุดแบบไดนามิก (คงไฟล์ทุกมัดในไบนารีขนาดใหญ่ VS ห้องสมุดแบบไดนามิกที่ช่วยให้ใช้งานร่วมกันในหมู่ executables รหัสที่แตกต่างกัน) ยังมีผลทางกฎหมาย

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

นี่เป็นปัญหาที่สำคัญยิ่งกว่าหากคุณตัดสินใจรวบรวมแอพพลิเคชั่นมือถือเช่น (ใน Android คุณมีตัวเลือกคงที่ vs ไดนามิกใน iOS ที่คุณทำไม่ได้ - มันคงที่เสมอ)


23

โปรแกรม C ++ นั้นสร้างขึ้นในสองขั้นตอน

  1. การคอมไพล์ - สร้างรหัสวัตถุ (.obj)
  2. การเชื่อมโยง - สร้างรหัสที่ปฏิบัติการได้ (.exe หรือ. dll)

ห้องสมุดคงที่ (.lib) เป็นเพียงชุดของไฟล์. obj และดังนั้นจึงไม่ใช่โปรแกรมที่สมบูรณ์ มันไม่ได้ผ่านขั้นตอนที่สอง (การเชื่อมโยง) ของการสร้างโปรแกรม ในขณะที่กำลังเป็นเหมือน exe และดังนั้นจึงเป็นโปรแกรมที่สมบูรณ์

หากคุณสร้างไลบรารีแบบคงที่จะไม่ได้เชื่อมโยงดังนั้นผู้ใช้ห้องสมุดแบบคงที่ของคุณจะต้องใช้คอมไพเลอร์ตัวเดียวกับที่คุณใช้ (ถ้าคุณใช้ g ++ พวกเขาจะต้องใช้ g ++)

หากคุณสร้าง dll ขึ้นมา (และสร้างขึ้นอย่างถูกต้อง ) คุณได้สร้างโปรแกรมที่สมบูรณ์ที่ผู้ใช้ทุกคนสามารถใช้ได้ไม่ว่าพวกเขาจะใช้คอมไพเลอร์ใด มีข้อ จำกัด หลายประการ แต่ในการส่งออกจาก dll หากต้องการความเข้ากันได้ข้ามคอมไพเลอร์


1
นี่คือข่าวสำหรับฉัน มีข้อ จำกัด อะไรบ้างในการคอมไพล์ข้ามเมื่อใช้ DLLs? มีโปรแกรมเมอร์สร้างโดยไม่จำเป็นต้อง toolchain เดียวกันดูเหมือนว่าเป็นประโยชน์อย่างมากสำหรับ DLLs
Dan

1
คำตอบนี้เป็นข้อมูล เพิ่มข้อแม้เล็กน้อย: consumers of your static library will have to use the same compiler that you usedถ้าห้องสมุดคงใช้ห้องสมุด C ++ #include <iostream>เช่น
trueadjustr

อย่างใดอย่างหนึ่งไม่สามารถใช้ c ++ dll ได้หากไม่ใช้คอมไพเลอร์ตัวเดียวกัน (เนื่องจากไม่มี c ++ abi มาตรฐานสัญลักษณ์จะถูกทำหลายรูปแบบ) ทั้ง dll และโมดูลไคลเอนต์ต้องใช้คอมไพเลอร์เดียวกันและการตั้งค่า
บิวด์

19

การสร้างห้องสมุดแบบคงที่

$$:~/static [32]> cat foo.c
#include<stdio.h>
void foo()
{
printf("\nhello world\n");
}
$$:~/static [33]> cat foo.h
#ifndef _H_FOO_H
#define _H_FOO_H

void foo();

#endif
$$:~/static [34]> cat foo2.c
#include<stdio.h>
void foo2()
{
printf("\nworld\n");
}
$$:~/static [35]> cat foo2.h
#ifndef _H_FOO2_H
#define _H_FOO2_H

void foo2();

#endif
$$:~/static [36]> cat hello.c
#include<foo.h>
#include<foo2.h>
void main()
{
foo();
foo2();
}
$$:~/static [37]> cat makefile
hello: hello.o libtest.a
        cc -o hello hello.o -L. -ltest
hello.o: hello.c
        cc -c hello.c -I`pwd`
libtest.a:foo.o foo2.o
        ar cr libtest.a foo.o foo2.o
foo.o:foo.c
        cc -c foo.c
foo2.o:foo.c
        cc -c foo2.c
clean:
        rm -f foo.o foo2.o libtest.a hello.o

$$:~/static [38]>

สร้างห้องสมุดแบบไดนามิก

$$:~/dynamic [44]> cat foo.c
#include<stdio.h>
void foo()
{
printf("\nhello world\n");
}
$$:~/dynamic [45]> cat foo.h
#ifndef _H_FOO_H
#define _H_FOO_H

void foo();

#endif
$$:~/dynamic [46]> cat foo2.c
#include<stdio.h>
void foo2()
{
printf("\nworld\n");
}
$$:~/dynamic [47]> cat foo2.h
#ifndef _H_FOO2_H
#define _H_FOO2_H

void foo2();

#endif
$$:~/dynamic [48]> cat hello.c
#include<foo.h>
#include<foo2.h>
void main()
{
foo();
foo2();
}
$$:~/dynamic [49]> cat makefile
hello:hello.o libtest.sl
        cc -o hello hello.o -L`pwd` -ltest
hello.o:
        cc -c -b hello.c -I`pwd`
libtest.sl:foo.o foo2.o
        cc -G -b -o libtest.sl foo.o foo2.o
foo.o:foo.c
        cc -c -b foo.c
foo2.o:foo.c
        cc -c -b foo2.c
clean:
        rm -f libtest.sl foo.o foo

2.o hello.o
$$:~/dynamic [50]>

13

ห้องสมุดคงได้รับการรวบรวมลงในลูกค้า . lib ถูกใช้ในเวลาคอมไพล์และเนื้อหาของไลบรารีกลายเป็นส่วนหนึ่งของการปฏิบัติการที่ใช้งานได้

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


13

คุณควรคิดอย่างรอบคอบเกี่ยวกับการเปลี่ยนแปลงเมื่อเวลาผ่านไปการกำหนดเวอร์ชันความเสถียรความเข้ากันได้และอื่น ๆ

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

หรือคุณต้องการแยกพวกเขาออกจากกันเพื่อให้คุณสามารถเปลี่ยนหนึ่งและมั่นใจว่าคุณไม่ได้แตกอีก จากนั้นใช้ lib แบบคงที่

DLL นรกคือเมื่อคุณน่าจะใช้ lib แบบคงที่ แต่คุณใช้ dll แทนและไม่ใช่ exes ทั้งหมดที่จะเข้ากันได้กับมัน


9

ไลบรารีแบบสแตติกจะต้องเชื่อมโยงกับการปฏิบัติการขั้นสุดท้าย มันจะกลายเป็นส่วนหนึ่งของปฏิบัติการและตามมันไปทุกที่ ไลบรารีแบบไดนามิกจะถูกโหลดทุกครั้งที่มีการเรียกใช้งานและยังคงแยกจากไฟล์ที่เรียกใช้งานเป็นไฟล์ DLL

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

คุณจะใช้ไลบรารีแบบคงที่ทุกครั้งที่คุณไม่มีเหตุผลในการใช้ไลบรารีแบบไดนามิก


คุณอาจใช้ DLL เมื่อแอปพลิเคชันอื่น ๆ ใช้ฟังก์ชันการทำงานเดียวกัน - ซึ่งสามารถลดรอยเท้า
ทิม

นอกจากนี้การขยายแนวคิดเริ่มต้นของคุณ "ปลั๊กอิน" สถาปัตยกรรมที่คุณต้องการอนุญาตการทำงานเพิ่ม / ไม่รู้จักในภายหลังโดยไม่ต้องสร้างหรือรีลีสใหม่สามารถทำได้กับไลบรารีแบบไดนามิกเท่านั้น
ทิม

8

บทความของ Ulrich Drepper ใน " How to Write Libraries ที่ใช้ร่วมกัน " เป็นแหล่งข้อมูลที่ดีที่ให้รายละเอียดว่าจะใช้ประโยชน์จากไลบรารีที่แชร์ได้อย่างไรหรือสิ่งที่เขาอ้างถึงว่าเป็น "Dynamic Shared Objects" (DSOs) มันเน้นเพิ่มเติมเกี่ยวกับไลบรารี่ที่แชร์ในรูปแบบไบนารี่ของELFแต่การสนทนาบางอย่างก็เหมาะสำหรับ Windows DLL เช่นกัน


5

สำหรับการอภิปรายที่ยอดเยี่ยมของหัวข้อนี้อ่านบทความของ Sun นี้

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


4

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


3

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

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


3

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

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

ถ้าคุณสามารถอยู่กับไลบรารีแบบคงที่ไปกับไลบรารีแบบคงที่


3

เราใช้ DLL จำนวนมาก (> 100) ในโครงการของเรา DLL เหล่านี้มีการพึ่งพาซึ่งกันและกันดังนั้นเราจึงเลือกการตั้งค่าการเชื่อมโยงแบบไดนามิก อย่างไรก็ตามมันมีข้อเสียดังต่อไปนี้:

  • เริ่มต้นช้า (> 10 วินาที)
  • ต้องมีการกำหนดรุ่น DLL เนื่องจาก windows จะโหลดโมดูลตามชื่อที่ไม่ซ้ำกัน องค์ประกอบที่เป็นลายลักษณ์อักษรของตัวเองจะได้รับรุ่นที่ผิดของ DLL (เช่นโหลดแล้วแทนที่จะเป็นชุดกระจายของตัวเอง)
  • เครื่องมือเพิ่มประสิทธิภาพสามารถเพิ่มประสิทธิภาพภายในขอบเขต DLL เท่านั้น ตัวอย่างเช่นเครื่องมือเพิ่มประสิทธิภาพพยายามวางข้อมูลและรหัสที่ใช้บ่อยซึ่งอยู่ติดกัน แต่จะไม่ทำงานข้ามขอบเขต DLL

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

  • exe ใช้ shared_lib1, shared_lib2
  • shared_lib1 ใช้ shared_lib2
  • shared_lib2

รหัสและตัวแปรของ shared_lib2 ควรมีอยู่ในการปฏิบัติการขั้นสุดท้ายที่ผสานได้เพียงครั้งเดียว ใครช่วยคำถามนี้ได้บ้าง


คุณไม่ได้ตั้งใจจะใช้คำสั่ง pre-compiler บางวิธีเพื่อหลีกเลี่ยงการทำซ้ำรหัสหรือไม่?
Paceman

การคอมไพล์ล่วงหน้าของ Afaiac ใช้ได้กับฐานต่อ (exe / dll / lib) เท่านั้น การคอมไพล์ล่วงหน้ามีความหมายเบื้องต้นเพื่อเพิ่มความเร็วในการรวบรวมแม้ว่ามันจะป้องกันการรวมหลาย ๆ อย่างภายในหน่วยการคอมไพล์ อย่างไรก็ตามมีเจ้าหน้าที่รักษาความปลอดภัยเป็นวิธีที่ดีกว่าเพื่อให้บรรลุผลนี้
gast128

2

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


2

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


2

ฉันจะให้กฎทั่วไปง่ายๆว่าถ้าคุณมี codebase ขนาดใหญ่ทั้งหมดนี้สร้างขึ้นจากห้องสมุดระดับล่าง (เช่นกรอบ Utils หรือ Gui) ซึ่งคุณต้องการแบ่งพาร์ติชันให้เป็นไลบรารีที่จัดการได้มากกว่า ห้องสมุดแบบไดนามิกไม่ได้ซื้ออะไรให้คุณจริงๆและมีความประหลาดใจน้อยลง - จะมีอินสแตนซ์เดียวของอินสแตนซ์เดียว

หากคุณมีห้องสมุดที่แยกออกจากส่วนอื่น ๆ ของ codebase (เช่นไลบรารีของบุคคลที่สาม) ให้ลองสร้าง dll ดู หากห้องสมุดเป็น LGPL คุณอาจต้องใช้ dll เนื่องจากเงื่อนไขการให้สิทธิ์ใช้งาน

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