2009-08-22 20 views
13
test.c: 

int main() 
{ 
    return 0; 
} 

tôi đã không sử dụng bất kỳ cờ (Tôi là một newb để gcc), chỉ lệnh:GCC: Chương trình trống == 23202 bytes?

gcc test.c 

Tôi đã sử dụng mới nhất TDM build of GCC trên win32. Kết quả thực thi là gần 23KB, quá lớn đối với một chương trình trống.

Làm cách nào để giảm kích thước tệp thực thi?

+0

Một đề xuất: Bạn có nhận được kết quả tương tự bằng cách sử dụng bản dựng minGW của GCC không? Tôi không chắc liệu kích thước đó có khác thường hay không, vì tôi cũng không quen với C++. – Macha

+0

UPX? http://upx.sourceforge.net/ – bobince

+0

Vâng, tôi biết UPX, nhưng vấn đề ở đây là: trình biên dịch không nên tạo ra ~ 23KB rác cho một chương trình trống. – George

Trả lời

36

Đừng làm theo các đề xuất của nó, nhưng vì mục đích giải trí, hãy đọc this 'story' về cách tạo nhị phân ELF nhỏ nhất có thể.

+6

+1 Thật thú vị khi đọc! –

+1

Chết tiệt, điều này không được coi là nghiêm túc. Bây giờ nó là câu trả lời được bình chọn nhiều nhất mà tôi đã đưa ra! – Novelocrat

+1

Bài viết được liên kết trong http://stackoverflow.com/questions/553029/what-is-the-smallest-possible-windows-pe-executable cũng rất thú vị. – bk1e

10

Theo mặc định, một số thư viện chuẩn (ví dụ: thời gian chạy C) được liên kết với tệp thực thi của bạn. Kiểm tra các phím --nostdlib --nostartfiles --nodefaultlib để biết chi tiết. Tùy chọn liên kết được mô tả here.

Đối với tùy chọn thứ hai của chương trình thực, hãy thử optimization options, ví dụ: -Os (tối ưu hóa cho kích thước).

+0

Điều này là đúng, nhưng thường là bạn _want_ những thư viện đó. –

+0

Đúng vậy. Các phím này tôi chỉ sử dụng cho các hệ thống nhúng. –

+0

Bạn đề xuất gì để bắt đầu?(Tôi mới sử dụng GCC, nhưng trước đây tôi đã sử dụng C rất nhiều trong VisualCpp) – George

21

Làm cách nào để giảm kích thước của nó?

  • Đừng làm điều đó. Bạn chỉ lãng phí thời gian của bạn.
  • Sử dụng -s cờ dải biểu tượng (gcc -s)
7

Trên thực tế, nếu mã của bạn không có gì, là nó thậm chí còn công bằng mà trình biên dịch vẫn tạo ra một thực thi? ;-)

Vâng, trên Windows mọi tệp thực thi sẽ vẫn có kích thước, mặc dù nó có thể hợp lý nhỏ. Với hệ thống MS-DOS cũ, một ứng dụng hoàn toàn không có gì sẽ chỉ là một vài byte. (Tôi nghĩ rằng bốn byte để sử dụng ngắt 21h để đóng chương trình.) Sau đó, một lần nữa, những ứng dụng được nạp thẳng vào bộ nhớ. Khi định dạng EXE trở nên phổ biến hơn, mọi thứ đã thay đổi một chút. Bây giờ các tập tin thực thi có thêm thông tin về quy trình, như việc di chuyển mã và phân đoạn dữ liệu cộng với một số tổng kiểm tra và thông tin phiên bản. Sự ra đời của Windows đã thêm một tiêu đề khác vào định dạng, để cho MS-DOS biết rằng nó không thể thực thi tệp thực thi vì nó cần chạy dưới Windows. Và Windows sẽ nhận ra nó mà không có vấn đề gì. Tất nhiên, định dạng thực thi cũng được mở rộng với thông tin tài nguyên, như bitmap, biểu tượng và biểu mẫu hộp thoại và nhiều, nhiều hơn nữa.

Tệp thực thi không có gì hiện nay có kích thước từ 4 đến 8 kilobyte, tùy thuộc vào trình biên dịch của bạn và mọi phương pháp bạn đã sử dụng để giảm kích thước của nó. Nó sẽ ở kích thước mà UPX thực sự sẽ dẫn đến các tập tin thực thi lớn hơn! Các byte bổ sung trong tệp thi hành của bạn có thể được thêm vì bạn đã thêm một số thư viện nhất định vào mã của mình. Đặc biệt là các thư viện với dữ liệu khởi tạo hoặc tài nguyên sẽ thêm một số lượng đáng kể các byte. Việc thêm thông tin gỡ lỗi cũng làm tăng kích thước của tệp thực thi.

Nhưng trong khi tất cả điều này làm cho một bài tập tốt đẹp ở việc giảm kích thước, bạn có thể tự hỏi nếu nó thực tế để chỉ tiếp tục lo lắng về sự cồng kềnh của các ứng dụng. Đĩa cứng hiện đại sẽ phân chia các tệp trong các phân đoạn và cho các đĩa thực sự lớn, sự khác biệt sẽ rất nhỏ. Tuy nhiên, số lượng rắc rối nó sẽ mất để giữ cho kích thước càng nhỏ càng tốt sẽ làm chậm tốc độ phát triển, trừ khi bạn là một nhà phát triển chuyên gia được sử dụng để tối ưu hóa. Những loại tối ưu hóa này không có xu hướng cải thiện hiệu suất và xem xét dung lượng đĩa trung bình của hầu hết các hệ thống, tôi không thấy lý do tại sao nó sẽ thực tế. (Tuy nhiên, tôi làm tối ưu hóa mã của riêng mình theo những cách tương tự nhưng sau đó một lần nữa, tôi có kinh nghiệm với những tối ưu hóa này.)


Quan tâm đến số EXE header? Nó bắt đầu bằng chữ MZ, cho "Mark Zbikowski".Phần đầu tiên là tiêu đề MS-DOS kiểu cũ cho các tập tin thực thi và được sử dụng làm sơ khai cho MS-DOS nói rằng chương trình là không thực thi MS-DOS. (Trong nhị phân, bạn có thể tìm thấy văn bản 'Chương trình này không thể chạy trong chế độ DOS.' Về cơ bản tất cả những gì nó làm: hiển thị thông báo đó. Tiếp theo là tiêu đề PE, Windows sẽ nhận ra và sử dụng thay cho MS-DOS Nó bắt đầu bằng các chữ cái PE for Portable Executable. Sau tiêu đề thứ hai này sẽ có bản thân thực thi, được chia thành nhiều khối mã và dữ liệu, tiêu đề chứa các bảng phân bổ lại đặc biệt cho hệ điều hành biết nơi tải một khối cụ thể. giữ này đến một giới hạn, thực thi cuối cùng có thể được nhỏ hơn 4 KB, nhưng 90% sau đó sẽ là thông tin tiêu đề và không có chức năng.

+3

Đối với một ứng dụng DOS, một lần thử đơn giản sẽ thực hiện. Tức là, 1 byte. –

+0

Một ret sẽ làm, nhưng quy tắc chính thức là bạn đã phải gọi là "Exit" ngắt. –

+0

Tôi đã xây dựng các tệp thực thi Windows (định dạng PE) thực hiện những điều hữu ích trong <4KB, sử dụng VS2005. Vì vậy, một thực thi không có gì chắc chắn không phải là 8KB. (Tại sao? Tự động kiểm tra đĩa CD, không khởi động một trình cài đặt EXE lớn nếu ứng dụng đã được cài đặt) – MSalters

2

mục đích của bài tập này là gì?

Ngay cả với một mức độ thấp ngôn ngữ như C, vẫn còn rất nhiều thiết lập mà có để happe n trước khi chính có thể được gọi. Một số thiết lập đó được xử lý bởi bộ tải (cần một số thông tin nhất định), một số được xử lý bởi mã gọi chính. Và sau đó có thể có một chút mã thư viện mà bất kỳ chương trình bình thường nào cũng phải có. Ít nhất, có lẽ có tham chiếu đến các thư viện chuẩn, nếu chúng nằm trong dll.

Kiểm tra kích thước nhị phân của chương trình trống là một bài tập vô giá trị trong và của chính nó. Nó nói với bạn không có gì. Nếu bạn muốn tìm hiểu điều gì đó về kích thước mã, hãy thử viết các chương trình không trống (và tốt hơn là không tầm thường). So sánh các chương trình sử dụng thư viện chuẩn với các chương trình tự làm mọi thứ.

Nếu bạn thực sự muốn biết điều gì đang diễn ra trong tệp nhị phân đó (và tại sao nó quá lớn), hãy tìm ra định dạng thực thi có được công cụ kết xuất nhị phân và tách rời nhau.

+0

Vì bạn không biết động cơ của OP, điều đó không đúng. Ông có thể quan tâm đến việc phát triển nhúng, ví dụ, kích thước mã quan trọng rất nhiều. – Novelocrat

+3

Kích thước mã của chương trình trống vẫn hoàn toàn không liên quan. Và nếu anh ta vào lập trình nhúng, nơi kích thước của các vấn đề của chương trình, thì bất cứ điều gì anh ta làm với trình biên dịch cửa sổ là không liên quan. –

+0

Kích thước mã của một chương trình trống không liên quan khi 1. bạn mã trình diễn, 2. bạn quan tâm đến cách hoạt động biên dịch, kết quả cuối cùng trong tệp thực thi cuối cùng 3. và cuối cùng khi bạn biết rằng một chương trình trống không nên ~ 23KB. Có thể không có sử dụng rõ ràng của một cái gì đó như thế này, nhưng nó không làm cho việc tìm hiểu về các cờ biên dịch không liên quan. – George

3

Tôi thích cách FAQ DJGPP addressed this nhiều nhiều năm trước:

Nói chung, đánh giá kích thước đang bằng cách nhìn vào kích thước của chương trình "Hello" là vô nghĩa, bởi vì chương trình như vậy bao gồm chủ yếu là khởi động mã. ... Hầu hết sức mạnh của tất cả các tính năng này đều bị lãng phí trong các chương trình "Hello". Không có điểm nào trong việc chạy tất cả mã đó chỉ để in chuỗi 15 byte và thoát.

+1

Toàn bộ điểm của chương trình trống là để xem chi phí. Tôi chỉ đơn giản là quan tâm đến cách biên dịch hoạt động, những gì kết thúc trong một nhị phân biên dịch sang một bên từ mã tôi đặt ở đó. – George

+2

Richard, đó không phải là tất cả những gì bạn đã hỏi trong câu hỏi của bạn. Bạn hỏi làm thế nào để thoát khỏi chi phí. Bạn đã không hỏi những gì trên bao gồm. –

0

Sử dụng GCC, biên dịch chương trình của bạn sử dụng -Os chứ không phải là một trong những lá cờ tối ưu hóa khác (-O2 hoặc -O3). Điều này nói với nó để tối ưu hóa cho kích thước chứ không phải là tốc độ. Ngẫu nhiên, nó đôi khi có thể làm cho các chương trình chạy nhanh hơn so với tốc độ tối ưu hóa sẽ có, nếu một số phân đoạn quan trọng xảy ra để phù hợp hơn độc đáo hơn. Mặt khác, -O3 thực sự có thể làm tăng kích thước mã.

Cũng có thể có một số cờ liên kết yêu cầu nó bỏ qua mã không sử dụng từ nhị phân cuối cùng.

+0

-Không có sự khác biệt nào đối với mã này. –

+1

Không ngạc nhiên, trong trường hợp này. Không có nhiều mã mà GCC thực sự chạm vào đây. – Novelocrat

11

Bỏ cuộc. Trên x86 Linux, gcc 4.3.2 tạo ra một nhị phân 5K. Nhưng chờ đã! Đó là với liên kết động! Mã nhị phân được liên kết tĩnh là hơn một nửa meg: 516K. Hãy thư giãn và học cách sống với sự sưng lên.

Và họ nói Modula-3 sẽ không bao giờ đi bất cứ đâu vì một số nhị phân thế giới chào 200K!


Trong trường hợp bạn tự hỏi điều gì đang diễn ra, thư viện Gnu C có cấu trúc bao gồm một số tính năng nhất định cho dù chương trình của bạn có phụ thuộc vào chúng hay không. Các tính năng này bao gồm các phần tử như malloc và miễn phí, dlopen, xử lý chuỗi và toàn bộ bucketload về những thứ dường như phải làm với ngôn ngữ và quốc tế, mặc dù tôi không thể tìm thấy bất kỳ trang người dùng nào có liên quan.

Tạo các tệp thi hành nhỏ cho các chương trình yêu cầu dịch vụ tối thiểu là không mục tiêu thiết kế cho glibc. Để công bằng, nó cũng đã được không mục tiêu thiết kế cho mọi hệ thống thời gian chạy mà tôi từng làm việc (khoảng nửa tá).

1

Chạy dải trên nhị phân để loại bỏ các biểu tượng. Với phiên bản gcc 3.4.4 (cygming special), tôi giảm từ 10k xuống 4K.

Bạn có thể thử liên kết thời gian chạy tùy chỉnh (Phần gọi chính) để thiết lập môi trường thời gian chạy của bạn. Tất cả các chương trình đều sử dụng cùng một chương trình để thiết lập môi trường thời gian chạy đi kèm với gcc nhưng đối với tệp thực thi của bạn, bạn không cần dữ liệu hoặc bộ nhớ zero'ed. Các phương tiện bạn có thể loại bỏ các chức năng thư viện không sử dụng như memset/memcpy và giảm kích thước CRT0. Khi tìm kiếm thông tin về cái nhìn này tại GCC trong môi trường nhúng. Các nhà phát triển nhúng là những người duy nhất sử dụng môi trường thời gian chạy tùy chỉnh.

Phần còn lại là chi phí cho hệ điều hành tải tệp thực thi. Bạn sẽ không giống nhau ở đó trừ khi bạn điều chỉnh bằng tay?

2

'size a.out' cho bạn biết về kích thước của đoạn mã, dữ liệu và phân đoạn bss là gì? Phần lớn mã có khả năng là mã khởi động (theo kiểu cổ điển là crt0.o trên các máy Unix) được gọi bởi o/s và thiết lập công việc (như phân loại đối số dòng lệnh thành argc, argv) trước khi gọi main().

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