# 53: Linker (Trình liên kết) không phải là một chương trình ma thuật gì cả đâu

Thường xuyên chán nản (nó lại xảy ra với tôi ngay trước khi tôi viết bài này), quan điểm của nhiều lập trình viên về quá trình chuyển từ mã nguồn sang thực thi được liên kết tĩnh trong một ngôn ngữ được biên dịch là:

  1. Chỉnh sửa mã nguồn
  • Biên dịch mã nguồn thành các tệp đối tượng
  • Một cái gì đó kỳ diệu xảy ra
  • Chạy thực thi Bước 3 đương nhiên là bước liên kết rồi. Tại sao tôi lại nói một điều thái quá lên như vậy? Tôi đã làm hỗ trợ công nghệ trong nhiều thập kỷ và tôi nhận được các câu hỏi sau đây:
  1. Trình liên kết nói def được định nghĩa nhiều lần..
  • Trình liên kết nói abc là một biểu tượng chưa được giải quyết.
  • Tại sao khả năng thực thi của tôi rất lớn?

Theo cuốn sách “What do I do now?” (tạm dịch là “Tôi phải làm gì bây giờ?), thông thường với các cụm từ “seems to” (dường như) và “somehow” (bằng cách nào đó) trộn lẫn vào, và sẽ có một sự khó khăn được sinh ra.Đó là “dường như” và “bằng cách nào đó” chỉ ra rằng quá trình liên kết được xem như là một quá trình kỳ diệu, và có lẽ chỉ có các pháp sư hay phù thủy mới có thể hiểu được. Quá trình biên dịch không gợi ra các loại cụm từ này, có thể ngầm đình rằng các lập trình viên thường hiểu cách trình biên dịch làm việc hoặc ít nhất là những gì họ làm.

Một linker là một chương trình rất ngu ngốc, dành cho người đi bộ, đơn giản. Tất cả những gì nó làm là nối các phần mã và dữ liệu của các tệp đối tượng lại với nhau, kết nối các tham chiếu đến các biểu tượng với định nghĩa của chúng, kéo các biểu tượng chưa được giải quyết ra khỏi thư viện và viết ra một tệp thực thi. Là nó đó.. Không có sự mê hoặc! Không có phép thuật. Sự nhàm chán trong việc viết một trình liên kết thường là tất cả về giải mã và tạo ra các định dạng tệp thường quá phức tạp, nhưng điều đó không thay đổi bản chất cơ bản của một trình liên kết.

Vì vậy, hãy nói rằng trình liên kết đang nói def được định nghĩa nhiều lần. Nhiều ngôn ngữ lập trình, như C, C ++ và D, có cả khai báo và định nghĩa. Các khai báo thường đi vào các tệp tiêu đề, như:

extern int iii;

tạo ra một tham chiếu bên ngoài đến ký hiệu iii. Mặt khác, một định nghĩa, thực sự đặt lưu trữ cho biểu tượng, thường xuất hiện trong tệp thực hiện và trông như thế này:

int iii = 3;

Có bao nhiêu định nghĩa có thể có cho mỗi biểu tượng? Như trong phim Highlander, chỉ có duy nhất một. Vậy, điều gì sẽ xảy ra nếu một định nghĩa về iii xuất hiện trong nhiều tệp thực hiện?

// File a.c int iii = 3;
// File b.c double iii(int x) { return 3.7; }

Trình liên kết sẽ phàn nàn về iii được nhân lên.

Không chỉ có thể có một, mà phải có một. Nếu iii chỉ xuất hiện dưới dạng tuyên bố, nhưng không bao giờ là định nghĩa, trình liên kết sẽ phàn nàn về iii là một biểu tượng chưa được giải quyết.

Để xác định lý do tại sao một thực thi là kích thước của nó, hãy xem tập tin bản đồ mà các trình liên kết tùy ý tạo ra.Một tệp bản đồ không có gì khác hơn là một danh sách tất cả các biểu tượng trong tệp thực thi cùng với địa chỉ của chúng.Điều này cho bạn biết các mô-đun đã được liên kết từ thư viện và kích thước của mỗi mô-đun. Bây giờ bạn có thể thấy nơi phình ra từ đâu.Thường thì sẽ có các mô-đun thư viện mà bạn không biết tại sao lại được liên kết bên trong. Để tìm ra nó, tạm thời xóa mô-đun đáng ngờ khỏi thư viện và xem lại. Lỗi biểu tượng không xác định sau đó được tạo sẽ cho biết ai đang tham chiếu mô-đun đó.

Mặc dù không phải lúc nào cũng rõ ràng ngay lập tức tại sao bạn nhận được một thông điệp liên kết cụ thể, nhưng không có gì kỳ diệu về các trình liên kết. Các cơ chế là đơn giản; đó là chi tiết bạn phải tìm ra trong từng trường hợp.