Làm thế nào chúng ta có thể chắc chắn rằng các thành phần thấp hơn của lập trình máy tính như trình biên dịch, trình biên dịch, hướng dẫn máy, v.v ... là hoàn hảo?


57

Vì chúng ta ngày càng trở nên phụ thuộc hơn vào điện toán, bao gồm các nhiệm vụ rất quan trọng của cuộc sống hàng ngày, tôi chỉ tự hỏi làm thế nào những thành phần quan trọng này được thử nghiệm.

Về mặt kỹ thuật, các trình biên dịch và trình biên dịch được thử nghiệm như thế nào? (Tôi cho rằng điều này liên quan đến vấn đề tạm dừng !!)


36
Bạn có thể muốn bắt đầu nghiên cứu của mình với "Ken Thompson Hack" Xem những phản ánh về niềm tin tin cậy
Bryan Oakley

7
Dưới đây là một ví dụ về trình biên dịch có bằng chứng chính xác: compcert.inria.fr/doc/index.html
Giorgio

8
Hầu hết các trình biên dịch / liên kết / trình biên dịch được kiểm tra sâu nhất bằng cách sử dụng chúng rất nhiều trong nhiều trường hợp khác nhau. Để tìm lỗi, không có gì ở trên có hàng triệu người dùng sử dụng trình biên dịch của bạn.
Bart van Ingen Schenau

3
và thêm Hệ điều hành vào danh sách.
Erik Eidt

Câu trả lời:


104

Bạn không thể chắc chắn, nhưng bạn chỉ cho rằng chúng là như vậy, cho đến khi bạn phát hiện ra chúng không phải. Đã có rất nhiều lỗi trong trình biên dịch và phần cứng trong những năm qua.

Cách chúng được kiểm tra, ví dụ như một trình biên dịch, là chúng được xác định rất hẹp và cứng nhắc, được viết cẩn thận, sau đó được kiểm tra với một bộ kiểm tra khổng lồ để xác minh tính chính xác. Thêm vào đó là cơ sở người dùng rộng rãi của trình biên dịch và nhiều lỗi sẽ được phát hiện và báo cáo. Một ứng dụng lên lịch hẹn nha sĩ, tương đối, có ít người dùng hơn, và vẫn còn ít khả năng phát hiện lỗi.

SQLite bao gồm khoảng 73k dòng mã, trong khi bộ thử nghiệm của nó bao gồm khoảng 91378k dòng mã, gấp hơn 1250 lần so với chính SQLite. Tôi hy vọng trình biên dịch và các công cụ cốt lõi khác có tỷ lệ tương tự. Bộ xử lý ngày nay được thiết kế chủ yếu bằng phần mềm, sử dụng các ngôn ngữ mô tả phần cứng như Verilog hoặc VHDL và những bộ xử lý này cũng chạy thử nghiệm phần mềm, cũng như các chân IO chuyên dụng để chạy tự kiểm tra tại điểm sản xuất.

Cuối cùng, đây là một trò chơi xác suất, và thử nghiệm lặp đi lặp lại và bao quát rộng rãi cho phép bạn đẩy xác suất lỗi xuống mức thấp chấp nhận được, giống như một dự án phần mềm khác.


7
Tôi thường tự hỏi câu hỏi tương tự như OP, nhưng liên quan đến DBMS. Bạn đã đưa ra một ví dụ tuyệt vời đã trả lời nó trong ngữ cảnh của SQLite. Cảm ơn bạn!
Brandon

7
+1 nhưng bằng cách nào đó tôi nghi ngờ rằng "trình biên dịch và các công cụ cốt lõi khác có tỷ lệ tương tự".
Mehrdad

5
Lưu ý rằng (1) SQLite thực sự có hai bộ thử nghiệm, với sự dư thừa không tầm thường giữa hai và (2) vẫn có những lỗi được tìm thấy trong SQLite mặc dù điều này.
Matthieu M.

7
Tôi đã có ấn tượng rằng SQLite là một trong những phần mềm "được thử nghiệm rộng rãi" nhất (về các dòng mã kiểm tra / dòng mã hoạt động) có sẵn để sử dụng chung, thậm chí còn hơn rất nhiều trình biên dịch. Nếu không có gì khác, một trình biên dịch đầy đủ tính năng là một phần mềm khổng lồ và tôi không thể tưởng tượng được nó có số lượng mã kiểm tra gấp ngàn lần. (GCC được báo cáo lên tới 14,5 triệu dòng. Có vẻ như không có khả năng bộ sưu tập trình biên dịch phù hợp chỉ là 14k LỘC hoặc họ có một cơ sở mã kiểm tra 14 tỷ dòng đang ngồi ở bên cạnh! :-P)
David Z

2
@DavidZ: Đó chắc chắn là dự án duy nhất tôi biết sử dụng thử nghiệm OOM mở rộng chẳng hạn (họ sử dụng một trình tiêm lỗi cho thử nghiệm và phát lại chúng một lần nữa và thất bại ở lần phân bổ thứ 1, sau đó ... cho đến khi toàn bộ thử nghiệm được thực thi).
Matthieu M.

46

Trong điều khoản của Giáo dân:

  1. Bạn không thể.
  2. Trình biên dịch và thông dịch viên được kiểm tra đơn vị như bất kỳ phần mềm (chuyên nghiệp) nào khác.
  3. Một thử nghiệm thành công không có nghĩa là một chương trình không có lỗi, nó chỉ có nghĩa là không có lỗi nào được phát hiện.
  4. Một cơ sở người dùng rộng rãi sử dụng trình biên dịch trong một thời gian dài là một chỉ số khá hay về việc nó có rất ít lỗi, bởi vì người dùng thường kiểm tra các trường hợp mà các nhà thiết kế không nghĩ tới.
  5. Là nguồn mở cũng là một chỉ số tốt. "Được cung cấp đủ nhãn cầu, tất cả các lỗi đều nông ... Với một cơ sở đồng thử nghiệm và nhà phát triển beta đủ lớn, hầu hết mọi vấn đề sẽ được mô tả nhanh chóng và cách khắc phục sẽ rõ ràng với ai đó." . Trình biên dịch nguồn đóng có thể có các lỗi phát sinh tại những thời điểm rất cụ thể hoặc tạo ra mã máy tối ưu ít hơn và công ty đằng sau nó chỉ đơn giản là không tiết lộ sự tồn tại của họ vì ưu tiên rất thấp trong bản đồ đường đi của sản phẩm.

Dòng dưới cùng:

Tôi muốn nói hãy dùng OOP ( O ld, O pen và P opular). Tôi chỉ tạo nên từ viết tắt đó.


19
+1 Để phát minh ra một TLA khác (từ viết tắt ba chữ cái) - thế giới vẫn chưa có đủ số đó.
s1lv3r

34
Ngoài ra, OOP không có ý nghĩa trong lập trình máy tính. Vì vậy, KTT (kudos to thee)!
Pierre Arlaud

15
Nhận xét của Pierre là một trò đùa @Dannnno.
yannis

19
Ngoài ra, nó có thể P opular, O ld và O pen. ;) Trên thực tế, đó là cách tôi xếp chúng theo thứ tự quan trọng.
jpmc26

23
@ jpmc26 Tôi sẽ đi với Thực tế, Cũ, Mở và Phổ biến. Về từ viết tắt ...
StoolOne

24

Đó là tất cả các con rùa xuống.

Không có gì là chắc chắn. Bạn không có lựa chọn nào khác ngoài việc giải quyết xếp hạng niềm tin.

Bạn có thể coi nó như một ngăn xếp: Toán học> Vật lý> Phần cứng> Phần sụn> Hệ điều hành> Trình biên dịch / Trình biên dịch / v.v.

Ở mỗi cấp độ, bạn có các bài kiểm tra mà bạn có thể thực hiện để cải thiện xếp hạng niềm tin của mình. Một số thử nghiệm này có chất lượng của bằng chứng chính thức, một số trong số chúng dựa trên quan sát, hầu hết là sự kết hợp của cả hai.

Phần khó khăn là làm sáng tỏ sự đệ quy trong một số thử nghiệm này bởi vì chúng tôi sử dụng các chương trình để làm bằng chứng và phân tích quan sát bây giờ, nơi nó trở nên quá khó để làm điều đó bằng tay.

Cuối cùng, mặc dù câu trả lời là bạn thử mọi thứ bạn có thể nghĩ ra. Phân tích tĩnh, làm mờ, mô phỏng, chạy với đầu vào cực kỳ được chọn có chủ đích hoặc đầu vào ngẫu nhiên, chạy / ánh xạ mọi đường dẫn điều khiển, bằng chứng chính thức, v.v. Về cơ bản, mục tiêu của bạn trong thử nghiệm phải luôn là làm mọi thứ có thể để chứng minh rằng sản phẩm của bạn (ví dụ như lý thuyết / chip / chương trình) không hoạt động như dự định. Nếu bạn nỗ lực thực sự mà vẫn thất bại thì bạn được phép cải thiện mức độ tin cậy về tính chính xác của sản phẩm.

Kiểm tra tốt nhất là một quá trình bán kết có nghĩa là có một lỗi mà cuối cùng bạn sẽ tìm thấy nó nhưng bạn không bao giờ có thể chắc chắn rằng bạn đã tìm thấy tất cả. Ngay cả với phần mềm được xác minh chính thức, bạn vẫn dựa vào vật lý, các công cụ được sử dụng để làm bằng chứng chính thức và rằng điều bạn chứng minh là cần thiết và đủ để chương trình của bạn thực hiện những gì (thường chủ quan) "dự định". Đó là không đề cập đến tất cả các thành phần khác mà bạn đang sử dụng không có bằng chứng chính thức.


17

Đây là một câu hỏi "nguy hiểm" cho các nhà phát triển mới ở chỗ họ sẽ bắt đầu đổ lỗi cho các công cụ của họ thay vì mã của họ (đã ở đó, thực hiện điều đó, thấy quá nhiều người làm điều đó). Mặc dù có lỗi trong trình biên dịch, môi trường thời gian chạy, HĐH, v.v., các nhà phát triển nên thực tế và nhớ rằng, cho đến khi có bằng chứng và kiểm tra đơn vị chứng minh khác, lỗi nằm trong mã của bạn .

Trong hơn 25 năm lập trình ở hầu hết C, C ++ và Java tôi đã tìm thấy:

  • hai lỗi do lỗi trình biên dịch (gcc và SunOS C)
  • khoảng một lần mỗi năm hoặc hai lỗi do sự cố JVM của Java (thường liên quan đến tiêu thụ bộ nhớ / bộ sưu tập rác)
  • khoảng một tháng một lần hoặc hai lỗi trong thư viện, thường được sửa bằng cách sử dụng phiên bản mới nhất hoặc trở lại phiên bản trước của thư viện

Tất cả các lỗi khác có liên quan trực tiếp đến một lỗi hoặc thường xuyên hơn là thiếu hiểu biết về cách thư viện hoạt động. Đôi khi những gì có vẻ là một lỗi là do sự không tương thích, ví dụ như cách cấu trúc lớp Java thay đổi đã phá vỡ một số thư viện AOP.


Tôi tò mò - năm nào dành cho ngôn ngữ nào? Quay trở lại thời kỳ EGCS trước khi C ++ được chuẩn hóa chính xác, các lỗi trình biên dịch không quá khó tìm ...
Charles Duffy

3
Trình biên dịch, cpu hoặc ngôn ngữ càng tối nghĩa thì càng dễ tìm thấy lỗi trong trình biên dịch (trước người khác), vì vậy việc tìm kiếm 2 trong GCC C là tốt :)
Surt

1
Khi điều đó xảy ra, tôi chỉ lãng phí khoảng một tháng cho rằng vấn đề tôi gặp phải là trong các tập lệnh gdb của tôi, hoặc sự hiểu biết của tôi về những gì tôi đang kiểm tra. Cuối cùng, tôi đã nghi ngờ, đơn giản hóa trường hợp thử nghiệm của mình và tìm thấy một lỗ hổng thiết kế trong thư viện (libkvm), khiến trình gỡ lỗi kernel không thể truy cập vào một số địa chỉ nhất định từ kết xuất lõi. Tức là YMMV - và tôi hạnh phúc nhất khi tôi tìm thấy một lỗi mới trong mã ngược dòng của tôi, đặc biệt là thứ tôi đang sử dụng thay vì phát triển.
Arlie Stephens

Tất nhiên đó không phải là lỗi trình biên dịch , hay thậm chí là một trong những thư viện được sử dụng phổ biến hơn. Và sự thật mà nói, tôi không tìm thấy lỗi ở những người có bất kỳ tần suất nào cả.
Arlie Stephens

@ArlieStephens Có một bài học ở đó: đơn giản hóa trường hợp thử nghiệm của bạn là điều bạn nên làm sớm khi bạn không tìm ra vấn đề. Bất kể vấn đề là của bạn hay của mã khác, điều đó sẽ giúp bạn thu hẹp nó. Thông thường, nếu vấn đề nằm ở mã khác, điều này sẽ dẫn đến, "bằng chứng và kiểm tra đơn vị chứng minh" như vậy.
jpmc26

8

Tôi nghĩ một điểm thú vị ở đây là phần lớn các giấy phép phần mềm thương mại (và thực sự là phần mềm nguồn mở) chỉ định cụ thể rằng bạn không thể tin tưởng vào phần mềm.

PHẦN MỀM ĐƯỢC CUNG CẤP "NHƯ VẬY", KHÔNG CÓ ĐẢM BẢO CỦA BẤT K K LOẠI NÀO, RPR RÀNG HAY NGỤ Ý, BAO GỒM NHƯNG KHÔNG GIỚI HẠN ĐẢM BẢO ĐẢM BẢO TUYỆT VỜI, PHÙ HỢP ĐỐI VỚI MỘT MỤC ĐÍCH THAM GIA VÀ KHÔNG PHÙ HỢP.

Từ thỏa thuận cấp phép Microsoft Word

. Ngoại trừ Bảo hành có giới hạn và trong phạm vi tối đa được luật pháp hiện hành cho phép, Microsoft và các nhà cung cấp của Microsoft cung cấp Phần mềm và dịch vụ hỗ trợ (nếu có) NHƯ VẬY VÀ VỚI TẤT CẢ CÁC TẤT CẢ, và từ đó từ chối tất cả các bảo hành và điều kiện khác, cho dù rõ ràng, ngụ ý hay theo luật định, bao gồm, nhưng không giới hạn ở bất kỳ (nếu có) ngụ ý bảo hành, nghĩa vụ hoặc điều kiện thương mại, phù hợp cho một mục đích cụ thể, về độ tin cậy hoặc tính sẵn có, tính chính xác hoặc tính hoàn chỉnh của kết quả, của nỗ lực của người lao động, thiếu vi-rút và thiếu sơ suất, tất cả liên quan đến Phần mềm và việc cung cấp hoặc không cung cấp hỗ trợ hoặc các dịch vụ, thông tin, phần mềm và nội dung liên quan khác thông qua Phần mềm hoặc phát sinh từ việc sử dụng Phần mềm .

Về bản chất, câu này trong giấy phép trong hầu hết mọi phần mềm mà bạn sử dụng đặc biệt cho bạn biết rằng bạn không thể tin tưởng vào phần mềm chứ đừng nói đến trình biên dịch được sử dụng.

Phần mềm giống như một lý thuyết khoa học, nó được coi là hoạt động như được chỉ định cho đến khi nó không hoạt động.


+1 để chỉ ra rằng chính giấy phép nói rằng không có phần mềm nào là hoàn hảo.
Tulains Córdova

3
Tôi rất hài lòng khi nhận thấy sự sai lệch so với thực tiễn này trong ViaVoice cho Mac của IBM. Thay vì thông lệ "nếu nó không hoạt động, quá tệ", họ thực sự đã nói điều gì đó như "Phần mềm được bảo hành để thực hiện theo quy định."
WGroleau

1
Một bản dịch ngôn ngữ đơn giản của cụm từ bảo hành cụ thể này là: "Đây có thể là một phần mềm hoặc nó có thể là một phần của nó. Nó có thể hoạt động. Nó có thể không. Ngay cả khi nó không hoạt động Làm những gì bạn muốn. Nhân tiện, chúng tôi có thể đã đánh cắp bitcoin của người khác. Thật tệ. Chúng tôi đã nhận được tiền của bạn và đã sử dụng nó để thuê rất nhiều luật sư. TRÒ CHƠI! ON! Nyah-nyah -nyah-nyah-nyaaah-naah! ". :-)
Bob Jarvis

2
@BobJarvis: Tuyên bố bảo hành yêu thích của tôi, được sử dụng trên một số phần mềm nguồn mở (như nmap IIRC), là "Nếu nó bị hỏng, bạn có thể giữ cả hai phần".
Peter Cordes

Tuyên bố này có mặt khắp nơi trong phần mềm nguồn mở và rất nhiều phần mềm nguồn đóng miễn phí. Nó không xuất hiện trong hầu hết các giấy phép phần mềm thương mại phải trả tiền.
jwg

2

Là một người viết trình biên dịch cho một ngôn ngữ toán học *, từ kinh nghiệm của tôi, tôi có thể nói về lý thuyết bạn không thể. Và một số lỗi chỉ đưa ra kết quả sai như (từ danh sách xấu hổ của tôi) tính toán 6/3*2từ bên phải 6/(3*2)và xuất ra 1 mà không gặp sự cố hoặc đưa ra các lỗi biên dịch vô nghĩa.

Nhưng IMHO nhiều trình biên dịch không có nhiều lỗi như các phần mềm khác vì:

  • Viết bài kiểm tra đơn vị là dễ dàng. Mỗi câu lệnh là một đơn vị và bạn có thể viết các bài kiểm tra đơn giản như:test_unit("2+(-2)*(-2+1)*3+1",9);
  • Một chương trình là sự kết hợp của các câu lệnh và để bất kỳ chương trình nào đưa ra kết quả chính xác, mỗi câu lệnh riêng lẻ phải đưa ra kết quả chính xác (phần lớn). Vì vậy, rất khó có bất kỳ lỗi nào trong khi chương trình cho kết quả chính xác.
  • Khi kích thước và số lượng chương trình bằng văn bản tăng, khả năng bắt lỗi tăng lên đáng kể.

Đối với người lắp ráp, hướng dẫn máy, vv, ở trên cũng giữ; mặt khác, xác minh và xác nhận trong thiết kế và sản xuất chip có nhiều quy trình nghiêm ngặt hơn vì đây là một doanh nghiệp lớn: tự động hóa thiết kế điện tử .

Trước khi đi vào sản xuất, mỗi CPU nên được kiểm tra nghiêm ngặt vì mỗi lỗi có giá gần vài triệu đô la: có chi phí sản xuất không định kỳ rất lớn trong sản xuất chip. Vì vậy, các công ty đã chi rất nhiều tiền và viết rất nhiều mã mô phỏng cho thiết kế của họ trước khi đi vào sản xuất, mặc dù điều này không đảm bảo 100% - ví dụ: lỗi Pentium FDIV.

Nói tóm lại, rất khó có khả năng có lỗi nghiêm trọng trong trình biên dịch, mã máy, v.v.

Ngôn ngữ toán khiêm tốn của tôi *


Intel kiểm tra CPU của họ bằng cách chạy các chuỗi hướng dẫn ngẫu nhiên và so sánh với một mô hình phần mềm, trong số những thứ khác: tweaker.net/reviews/740/4/ . Đây là lý do tại sao bạn thường thấy errata thực sự tối nghĩa được công bố, đối với một số hướng dẫn thực sự không thể thực hiện được trong một chế độ bất thường.
Peter Cordes

0

Hoàn mỹ? Họ không phải. Gần đây tôi đã cài đặt một số "cập nhật" và đã vài tháng (và một số phần mã được lập trình lại) sau đó trước khi trang ASP.NET của tôi hoạt động bình thường trở lại, do những thay đổi không giải thích được về cách thức hoạt động của những thứ cơ bản khác nhau hoặc thất bại.

Tuy nhiên, chúng được thử nghiệm và sau đó được sử dụng bởi nhiều người định hướng chi tiết rất thông minh, những người có xu hướng chú ý và báo cáo và sửa chữa hầu hết mọi thứ. Stack Exchange là một ví dụ tuyệt vời (và cải thiện) cách tất cả những người sử dụng các công cụ đó giúp kiểm tra và phân tích cách thức các công cụ cấp thấp và phức tạp đáng kinh ngạc này hoạt động, ít nhất là theo cách sử dụng thực tế.

Nhưng hoàn hảo, không. Mặc dù bạn cũng có thể thấy mọi người trên Stack Exchange đạt được cái nhìn sâu sắc ấn tượng về các chi tiết hiệu suất và các tiêu chuẩn và sự tuân thủ tiêu chuẩn, luôn có những sai sót và không hoàn hảo, đặc biệt là khi những người khác nhau có ý kiến ​​khác nhau về lỗ hổng.


-1

Để cho thấy rằng các hệ thống cơ bản là hoàn hảo bạn hoặc

a) Cần chứng minh họ hoàn hảo

  1. Chứng minh toán học
  2. Chỉ thực tế có thể cho các chương trình tầm thường

b) Thực hiện một bài kiểm tra toàn diện

  1. Chỉ có thể cho các chương trình tầm thường và một số chương trình đơn giản
  2. Ngay khi một yếu tố thời gian bước vào thử nghiệm, không thể thực hiện một thử nghiệm toàn diện vì thời gian có thể bị chia vô thời hạn.
  3. Ngoài các chương trình tầm thường, các tùy chọn thực thi có thể bùng nổ theo cấp số nhân.

Trong kiểm thử phần mềm, kiểm tra toàn diện chỉ được sử dụng trong kiểm thử đơn vị một số chức năng đơn giản.

Ví dụ: Bạn muốn kiểm tra đầu vào utf-8 8 ký tự cho một số trường, bạn có thể chọn cắt đầu vào với 8 lần độ dài tối đa 6 của utf-8 tính bằng byte, thực sự có 8 * 6 = 48 byte để thực sự có số lượng hữu hạn của các khả năng.

Bây giờ bạn có thể nghĩ rằng bạn chỉ cần kiểm tra 1.112.064 điểm mã hợp lệ của mỗi trong số 8 ký tự, nghĩa là. 1.112.064 ^ 8 (giả sử 10 ^ 48) thử nghiệm (điều này khó có thể thực hiện được), nhưng bạn thực sự phải kiểm tra từng giá trị của từng trong số 48 byte hoặc 256 ^ 48, khoảng 10 ^ 120, độ phức tạp tương tự như cờ vua so với tổng số nguyên tử trong vũ trụ khoảng 10 ^ 80.

Thay vào đó, bạn có thể sử dụng, theo thứ tự nỗ lực ngày càng tăng và mỗi bài kiểm tra nên bao gồm tất cả các lần trước:

a) kiểm tra một mẫu tốt và xấu.

b) bảo hiểm mã, tức là. hãy thử kiểm tra từng dòng mã, tương đối đơn giản đối với hầu hết các mã. Bây giờ bạn có thể tự hỏi 1% mã cuối cùng mà bạn không thể kiểm tra là gì ... lỗi, mã chết, ngoại lệ phần cứng, v.v.

c) phạm vi bảo hiểm đường dẫn, tất cả các kết quả của tất cả các chi nhánh trong tất cả các kết hợp đều được kiểm tra. Bây giờ bạn biết tại sao bộ phận kiểm tra ghét bạn khi các chức năng của bạn chứa hơn 10 điều kiện. Ngoài ra, bạn tự hỏi tại sao 1% cuối cùng không thể được kiểm tra ... một số chi nhánh phụ thuộc vào các chi nhánh trước đó.

d) kiểm tra dữ liệu, kiểm tra một số mẫu có giá trị biên, giá trị có vấn đề phổ biến và số ma thuật, các giá trị zero, -1, 1, min +/- 1, max +/- 1, 42, rnd. Nếu điều này không cung cấp cho bạn phạm vi bảo hiểm đường dẫn, bạn biết rằng bạn đã nắm bắt được tất cả các giá trị trong phân tích của mình.

Nếu bạn đã làm điều này, bạn nên sẵn sàng cho kỳ thi nền tảng ISTQB.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.