2008-10-23 43 views
66

Bạn sẽ phát hiện mã chết như thế nào trong mã C/C++? Tôi có một cơ sở mã khá lớn để làm việc với và ít nhất 10-15% là mã chết. Có bất kỳ công cụ dựa trên Unix nào để xác định các khu vực này không? Một số đoạn mã vẫn còn sử dụng rất nhiều tiền xử lý, có thể tự động xử lý quá trình đó?Phát hiện mã chết trong dự án C/C++ cũ

+2

Có câu hỏi tương tự với nhiều hoạt động hơn tại đây: http://stackoverflow.com/questions/4813947/how-can-i-know-which-parts-in-the-code-are-never-used/ –

Trả lời

30

Bạn có thể sử dụng công cụ phân tích phạm vi mã cho mục đích này và tìm các vị trí không sử dụng trong mã của bạn.

Công cụ phổ biến cho chuỗi công cụ gcc là gcov, cùng với giao diện đồ họa lcov (http://ltp.sourceforge.net/coverage/lcov.php).

Nếu bạn sử dụng gcc, bạn có thể biên dịch bằng hỗ trợ gcov, được bật bởi cờ '--coverage'. Tiếp theo, chạy ứng dụng của bạn hoặc chạy bộ thử nghiệm của bạn với công cụ hỗ trợ gcov này.

Về cơ bản gcc sẽ phát ra một số tệp phụ trong quá trình biên dịch và ứng dụng cũng sẽ phát ra một số dữ liệu bảo hiểm trong khi chạy. Bạn phải thu thập tất cả các tệp (.gcdo và .gcda). Tôi không đi sâu vào chi tiết ở đây, nhưng có thể bạn cần phải đặt hai biến môi trường để thu thập dữ liệu vùng phủ sóng theo cách thông minh: GCOV_PREFIX và GCOV_PREFIX_STRIP ...

Sau khi chạy, bạn có thể đặt tất cả dữ liệu vùng phủ sóng với nhau và chạy nó thông qua các công cụ lcov. Việc hợp nhất tất cả các tệp tin bảo hiểm từ các lần thử nghiệm khác nhau cũng có thể xảy ra, mặc dù có liên quan một chút.

Dù sao đi nữa, bạn kết thúc với một tập hợp các trang web hiển thị một số thông tin bảo hiểm, chỉ ra các đoạn mã không có vùng phủ sóng và do đó, không được sử dụng.

Tắt khóa học, bạn cần phải kiểm tra kỹ xem các phần mã không được sử dụng trong mọi tình huống và rất nhiều phụ thuộc vào việc kiểm tra của bạn thực hiện tốt các codebase như thế nào. Nhưng ít nhất, điều này sẽ cung cấp cho một ý tưởng về các ứng cử viên mã chết có thể ...

+0

Tôi vẫn còn bị mắc kẹt với Sun C + + trình biên dịch nhưng chúng tôi có gcc di chuyển đang được tiến hành vì vậy tôi sẽ cố gắng này ra. Cảm ơn. – Nazgob

+0

Mã phân tích Bảo hiểm (chẳng hạn như 'gcov') có thể cung cấp dữ liệu mà mã không được bao phủ bởi (các) hoạt động cụ thể của mã phần mềm không được bảo hiểm không nhất thiết là mã chết. Một hoạt động khác của phần mềm (như tùy chọn biên dịch khác nhau, tùy chọn thời gian chạy khác nhau hoặc dữ liệu đầu vào khác nhau) hoặc đường dẫn thực thi khác (như xử lý lỗi) có thể kích hoạt một hàm không được gọi trước đó. – Arun

1

Bullseye công cụ bảo hiểm sẽ hữu ích. Nó không phải là miễn phí mặc dù.

+0

nó có giá trị tiền? Bất kỳ kinh nghiệm với nó? Họ có một thử nghiệm vì vậy tôi có thể kiểm tra xem nó ra, nếu nó hoạt động, chúng tôi có thể mua nó :) – Nazgob

+0

Có .. Tôi đã sử dụng trên nền tảng Symbian ...Chắc chắn giá trị của nó mua nó – Ashwin

4

Cách tiếp cận của bạn phụ thuộc vào các bài kiểm tra tính khả dụng (tự động). Nếu bạn có một bộ thử nghiệm mà bạn tin cậy để trang trải đủ lượng chức năng, bạn có thể sử dụng phân tích mức độ phù hợp, như các câu trả lời trước đã được đề xuất.

Nếu bạn không may mắn như vậy, bạn có thể muốn xem xét các công cụ phân tích mã nguồn như SciTools 'Hiểu điều đó có thể giúp bạn phân tích mã của mình bằng nhiều báo cáo phân tích được tích hợp sẵn. Trải nghiệm của tôi với công cụ đó bắt đầu từ 2 năm trước, vì vậy tôi không thể cung cấp cho bạn nhiều chi tiết, nhưng điều tôi nhớ là họ có hỗ trợ ấn tượng với thời gian sửa lỗi và trả lời câu hỏi rất nhanh.

Tôi tìm thấy một trang trên static source code analysis liệt kê nhiều công cụ khác.

Nếu điều đó không giúp bạn đủ, hoặc bạn đặc biệt quan tâm đến việc tìm ra mã chết liên quan đến tiền xử lý, tôi khuyên bạn nên đăng thêm một số chi tiết về mã. Ví dụ: nếu chủ yếu liên quan đến các kết hợp khác nhau của cài đặt #ifdef, bạn có thể viết tập lệnh để xác định cài đặt (kết hợp) và tìm ra kết hợp nào chưa bao giờ thực sự được tạo, v.v.

16

Biên dịch dưới gcc bằng -Wunreachable -code.

Tôi nghĩ rằng phiên bản mới hơn, kết quả tốt hơn bạn sẽ nhận được, nhưng tôi có thể sai lầm trong ấn tượng của tôi rằng đó là điều họ đã tích cực làm việc.Lưu ý rằng điều này không phân tích lưu lượng, nhưng tôi không tin nó cho bạn biết về "mã" đã chết trước khi nó rời khỏi bộ tiền xử lý, bởi vì nó không bao giờ được phân tích bởi trình biên dịch. Nó cũng sẽ không phát hiện ví dụ các hàm được xuất mà không bao giờ được gọi, hoặc mã xử lý trường hợp đặc biệt mà chỉ xảy ra là không thể bởi vì không có gì gọi hàm với tham số đó - bạn cần mã bảo hiểm cho điều đó (và chạy các kiểm tra chức năng, không phải kiểm thử đơn vị. giả định để có phạm vi mã 100% và do đó thực thi các đường dẫn mã bị 'chết' khi ứng dụng liên quan). Tuy nhiên, với những hạn chế trong tâm trí đó là một cách dễ dàng để bắt đầu tìm kiếm các thói quen hoàn toàn bị bollixed nhất trong cơ sở mã.

This CERT advisory lists some other tools for static dead code detection

+2

Câu trả lời này không hợp lệ với thực tế là tùy chọn -Wunreachable-code đã bị xóa khỏi gcc. http://gcc.gnu.org/ml/gcc-help/2011-05/msg00360.html –

+0

Xấu hổ. Đối với nhiều mục đích "không ổn định" phát hiện mã chết vẫn còn tốt hơn so với không có gì. Ngoài bất cứ điều gì khác, phát hiện mã chết hoàn hảo nói chung là không thể (ngăn chặn vấn đề), vì vậy mọi người đều biết rằng bất cứ công cụ nào họ sử dụng đều không hoàn hảo. Có lẽ ai đó thực sự quan tâm rằng nó không hoàn hảo hơn với '-O0' hơn là với' -O3', hoặc không muốn cảnh báo mới bất cứ khi nào trình tối ưu hóa được cải thiện. –

+3

Tuy nhiên, nếu mã của bạn không sử dụng các tính năng mới, bạn vẫn có thể sử dụng gcc cũ làm công cụ phân tích tĩnh. Vì vậy, câu trả lời của tôi không phải là * hoàn toàn * sai. Bit của một phạm vi tiếp cận, tôi biết ;-) –

4

Cả MozillaOpen Office có giải pháp cây nhà lá vườn.

+0

Cả hai liên kết là không thể tiếp cận bây giờ. Ai có thể cập nhật? – syam

+1

Tôi đã chuyển liên kết đầu tiên từ bài đăng trên blog sang trang tài liệu (hy vọng dài hơn). Liên kết Open Office xuất hiện để hoạt động. –

4

g ++ 4.01 -Wunreachable-code cảnh báo về mã không thể truy cập được trong một hàm, nhưng không cảnh báo về các chức năng không sử dụng.

int foo() { 
    return 21; // point a 
} 

int bar() { 
    int a = 7; 
    return a; 
    a += 9; // point b 
    return a; 
} 

int main(int, char **) { 
    return bar(); 
} 

g ++ 4.01 sẽ đưa ra cảnh báo về điểm b, nhưng không nói gì về foo() (điểm a) mặc dù không thể truy cập được trong tệp này. Hành vi này là chính xác mặc dù đáng thất vọng, bởi vì một trình biên dịch không thể biết rằng hàm foo() không được khai báo bên ngoài trong một số đơn vị biên dịch khác và được gọi từ đó; chỉ một mối liên kết có thể chắc chắn.

3

Phân tích mã chết như thế này yêu cầu phân tích toàn cầu toàn bộ dự án của bạn. Bạn không thể có được thông tin này bằng cách phân tích các đơn vị dịch một cách riêng lẻ (tốt, bạn có thể phát hiện các thực thể chết nếu chúng hoàn toàn nằm trong một đơn vị dịch, nhưng tôi không nghĩ đó là những gì bạn đang thực sự tìm kiếm).

Chúng tôi đã sử dụng Bộ công cụ tái cấu trúc phần mềm DMS của chúng tôi để thực hiện chính xác mã Java, bằng cách phân tích tất cả các đơn vị biên dịch cùng một lúc, xây dựng bảng biểu tượng cho mọi thứ và theo dõi tất cả các tham chiếu. Một định nghĩa cấp cao nhất không có tham chiếu và không có yêu cầu về một mục API bên ngoài đã chết. Công cụ này cũng tự động loại bỏ mã chết, và cuối cùng bạn có thể chọn những gì bạn muốn: báo cáo của các thực thể chết, hoặc mã bị tước bỏ các thực thể đó.

DMS cũng phân tích cú pháp C++ bằng nhiều phương ngữ (EDIT tháng 2 năm 2014: including MS and GCC versions of C++14 [EDIT Nov 2017: now C++17]) và xây dựng tất cả các bảng biểu tượng cần thiết. Theo dõi các tham chiếu đã chết sẽ đơn giản từ điểm đó. DMS cũng có thể được sử dụng để loại bỏ chúng. Xem http://www.semanticdesigns.com/Products/DMS/DMSToolkit.html

4

Chỉ với mã C và giả định rằng mã nguồn của toàn bộ dự án có sẵn, hãy khởi chạy phân tích bằng công cụ Nguồn mở Frama-C. Bất kỳ tuyên bố nào của chương trình hiển thị màu đỏ trong GUI là mã chết.

Nếu bạn gặp sự cố "mã chết", bạn cũng có thể quan tâm xóa "mã dự phòng", mã được thực hiện nhưng không đóng góp vào kết quả cuối cùng. Điều này yêu cầu bạn cung cấp mô hình hóa chính xác các chức năng I/O (bạn sẽ không muốn để xóa một tính toán có vẻ "rảnh" nhưng được sử dụng làm đối số cho printf). Frama-C có một tùy chọn để chỉ ra mã dự phòng.

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