2009-12-05 21 views
19

xem xét mã này:Tại sao tạo tệp .a từ .o để liên kết tĩnh?

one.c:

#include <stdio.h> 

int one() { 
    printf("one!\n"); 
    return 1; 
} 

two.c:

#include <stdio.h> 

int two() { 
    printf("two!\n"); 
    return 2; 
} 

prog.c

#include <stdio.h> 

int one(); 
int two(); 

int main(int argc, char *argv[]) 
{ 
    one(); 
    two(); 

    return 0; 
} 

Tôi muốn liên kết các chương trình này với nhau. Vì vậy, tôi làm điều này:

gcc -c -o one.o one.c 
gcc -c -o two.o two.c 
gcc -o a.out prog.c one.o two.o 

Điều này chỉ hoạt động tốt.

Hoặc tôi có thể tạo ra một thư viện tĩnh:

ar rcs libone.a one.o 
ar rcs libtwo.a two.o 
gcc prog.c libone.a libtwo.a 
gcc -L. prog.c -lone -ltwo 

Vì vậy, câu hỏi của tôi là: tại sao tôi sẽ sử dụng phiên bản thứ hai - một trong những nơi mà tôi đã tạo ra một ".a" file - chứ không phải là liên kết của tôi". o "tệp? Cả hai dường như liên kết tĩnh, vậy có lợi thế hay sự khác biệt về kiến ​​trúc trong cái này so với cái khác không?

Trả lời

38

Thông thường thư viện là tập hợp các tệp đối tượng có thể được sử dụng trong nhiều chương trình.

Trong ví dụ của bạn không có lợi thế, nhưng bạn có thể đã thực hiện:

ar rcs liboneandtwo.a one.o two.o 

Sau đó liên kết chương trình của bạn trở nên đơn giản hơn:

gcc -L. prog.c -loneandtwo 

Nó thực sự là một vấn đề của bao bì. Bạn có một tập hợp các tệp đối tượng tự nhiên tạo thành một tập hợp các chức năng liên quan có thể được tái sử dụng trong nhiều chương trình không? Nếu vậy, sau đó chúng có thể được lưu trữ một cách hợp lý vào một thư viện tĩnh, nếu không thì có lẽ không có lợi thế nào.

Có một sự khác biệt quan trọng trong bước liên kết cuối cùng. Bất kỳ tệp đối tượng nào bạn đã liên kết sẽ được bao gồm trong chương trình cuối cùng. Các tệp đối tượng nằm trong thư viện chỉ được bao gồm nếu chúng giúp giải quyết bất kỳ ký hiệu không xác định nào trong các tệp đối tượng khác. Nếu họ không làm như vậy, họ sẽ không được liên kết với bản thực thi cuối cùng.

2

Về mặt kỹ thuật, kết quả giống hệt nhau. Thông thường, bạn tạo các thư viện cho các hàm tiện ích, do đó, thay vì cho phép trình liên kết với hàng tá tệp đối tượng, bạn chỉ cần liên kết thư viện.

BTW, hoàn toàn không có ý nghĩa gì khi tạo tệp .a chỉ chứa một tệp .o.

+2

Kết quả thường rất khác nhau. Nó xảy ra giống nhau trong ví dụ giả tạo này. – UncleO

1

Lợi thế chính là khi bạn phải liên kết, bạn chỉ có thể chỉ định một thư viện thay vì tất cả các tệp đối tượng riêng biệt. Ngoài ra còn có một lợi thế nhỏ trong việc quản lý các tập tin, nhận được để đối phó với một thư viện thay vì một loạt các tập tin đối tượng. Tại một thời điểm, điều này cũng đã tiết kiệm đáng kể không gian đĩa, nhưng giá ổ đĩa cứng hiện tại làm cho điều đó ít quan trọng hơn.

2

Bạn có thể đặt một bộ sưu tập tệp trong tệp lưu trữ (.a) để sử dụng lại sau này. Thư viện chuẩn là một ví dụ điển hình.

Thỉnh thoảng có ý nghĩa khi tổ chức các dự án lớn thành thư viện.

12

Sự khác biệt sẽ ở kích thước của tệp thực thi, mặc dù có thể không dành cho ví dụ của bạn.

Khi liên kết đến thư viện, chỉ các bit được sử dụng bởi tệp thi hành của bạn mới được kết hợp. Khi liên kết một tệp đối tượng, bạn lấy toàn bộ thứ. Ví dụ, nếu thi hành của bạn phải bao gồm mọi chức năng toán học trong thư viện toán khi bạn chỉ sử dụng một, nó sẽ lớn hơn nhiều so với nó cần thiết và chứa nhiều mã không sử dụng.

Thật thú vị khi tương phản điều này với mô hình liên kết động của Windows. Ở đó, hệ điều hành phải tải tất cả các Dll (thư viện liên kết động) hoàn toàn là việc sử dụng thực thi của bạn, điều này có thể dẫn đến sưng lên trong RAM. Ưu điểm của mô hình như vậy là tệp thực thi của bạn nhỏ hơn và các Dll được liên kết có thể đã có trong bộ nhớ được một số tệp thực thi khác sử dụng, vì vậy chúng không cần phải tải lại.

Trong liên kết tĩnh, các hàm thư viện được tải riêng cho từng tệp thực thi.

0

Bất cứ khi nào tôi được hỏi câu hỏi này (bởi người làm mới trong nhóm của tôi), "tại sao (hoặc đôi khi là 'cái gì là') a .a?", Tôi sử dụng câu trả lời dưới đây sử dụng tệp .zip.

"Dấu chấm giống như tệp zip của tất cả các dotOh mà bạn muốn liên kết trong khi tạo exe/lib. Tiết kiệm dung lượng đĩa, cộng với không cần phải nhập tên của tất cả các dấu chấm liên quan."

cho đến nay, điều này dường như khiến họ hiểu. ;)

Các vấn đề liên quan