Tại sao chúng ta không nghiên cứu nhiều hơn về việc đảm bảo thời gian biên dịch?


12

Tôi yêu tất cả thời gian biên dịch và tôi thích ý tưởng rằng một khi bạn biên dịch một chương trình, rất nhiều đảm bảo được thực hiện về việc thực thi. Nói chung, một hệ thống kiểu tĩnh (Haskell, C ++, ...) dường như mang lại sự đảm bảo thời gian biên dịch mạnh hơn bất kỳ hệ thống kiểu động nào.

Từ những gì tôi hiểu, Ada thậm chí còn đi xa hơn trong việc kiểm tra thời gian biên dịch và có thể phát hiện ra một loạt lỗi lớn hơn trước khi thực hiện. Nó cũng được coi là khá an toàn, vì đôi khi, nó được chọn cho các lĩnh vực tế nhị (khi lỗi lập trình có thể phải trả giá bằng mạng sống của con người).

Bây giờ, tôi tự hỏi: nếu bảo đảm tĩnh mạnh hơn, dẫn đến mã được ghi lại nhiều hơn và an toàn, thì tại sao chúng ta không nghiên cứu nhiều hơn theo hướng đó?

Một ví dụ về thứ gì đó dường như bị thiếu, sẽ là ngôn ngữ thay vì xác định loại chung intcó phạm vi được xác định bởi số bit của kiến ​​trúc cơ bản, người ta có thể có phạm vi (trong ví dụ sau Int [a..b]mô tả loại số nguyên nằm giữa bao gồm a và b):

a : Int [1..24]
b : Int [1..12]
a + b : Int [2..36]
a - b : Int [-11..23]
b - a : Int [-23..11]

hoặc (lấy cái này từ Ada):

a : Int [mod 24]
b : Int [mod 24]
a + b : Int [mod 24]

Ngôn ngữ này sẽ chọn loại cơ bản tốt nhất cho phạm vi và sẽ thực hiện kiểm tra thời gian biên dịch trên các biểu thức. Vì vậy, ví dụ, được đưa ra:

a : Int [-3..24]
b : Int [3..10]

sau đó:

a / b

sẽ không bao giờ được xác định.

Đây chỉ là một ví dụ nhưng tôi cảm thấy như có nhiều hơn nữa chúng ta có thể thực thi vào thời gian biên dịch. Vì vậy, tại sao dường như có rất ít nghiên cứu về điều này? Các thuật ngữ kỹ thuật mô tả ý tưởng này là gì (để tôi có thể tìm thêm thông tin về chủ đề này)? Các giới hạn là gì?


2
Pascal có các kiểu con số nguyên (ví dụ, thập niên 1960), nhưng thật không may, hầu hết các triển khai chỉ kiểm tra chúng khi chạy (int (-1..4) là gán tương thích với int (100..200) tại thời gian biên dịch). Có những lợi ích hạn chế từ đó, và lập trình dựa trên hợp đồng mở rộng ý tưởng theo hướng tốt hơn (ví dụ như Eiffel). Các ngôn ngữ như C # cố gắng để có được một số lợi ích đó với các thuộc tính, tôi đã không sử dụng chúng nên không chắc chúng hữu ích như thế nào trong thực tế.

1
@: Các thuộc tính trong C # chỉ là các lớp siêu dữ liệu, vì vậy mọi xác thực dữ liệu sẽ xảy ra khi chạy.
Robert Harvey

8
Làm thế nào để bạn biết có ít nghiên cứu về điều này? Hãy thử googling dependent typehoặc refinement type.
Phil

3
Tôi đồng ý rằng tiền đề dường như là thiếu sót; đây chắc chắn là một lĩnh vực nghiên cứu tích cực. Công việc không bao giờ được thực hiện . Do đó, tôi không hoàn toàn thấy câu hỏi này có thể được trả lời như thế nào.
Raphael

1
@Robert Harvey: Việc ADA cung cấp nhiều bảo đảm hơn không có nghĩa là trình biên dịch sẽ bắt được tất cả các lỗi, nó sẽ chỉ khiến các lỗi ít xảy ra hơn.
Giorgio

Câu trả lời:


11

Tôi không ở một vị trí để nói bao nhiêu nhiều nghiên cứu cần được thực hiện về chủ đề này, nhưng tôi có thể nói với bạn rằng đó nghiên cứu đang được thực hiện, ví dụ như VeriSoft XT chương trình được tài trợ bởi chính phủ Đức.

Các khái niệm mà tôi nghĩ rằng bạn đang tìm kiếm được gọi là xác minh chính thứclập trình dựa trên hợp đồng , trong đó cái sau là cách thân thiện với lập trình viên. Trong lập trình dựa trên hợp đồng, trước tiên bạn viết mã của bạn như bình thường và sau đó chèn các hợp đồng được gọi là mã. Một ngôn ngữ có thể sử dụng dễ dàng dựa trên mô hình này là Spec # của Microsoft Research và tiện ích mở rộng Mã hợp đồng tương tự nhưng hơi kém về chức năng cho C # mà bạn có thể thử trực tuyến (chúng cũng có các công cụ tương tự cho các ngôn ngữ khác, hãy kiểm tra ris4fun ). "Int với loại phạm vi" mà bạn đã đề cập sẽ được phản ánh bởi hai hợp đồng trong một hàm:

Contract.Requires(-3 <= a && a <= 24);
Contract.Requires( 3 <= b && b <= 10);

Nếu bạn muốn gọi hàm đó, thì bạn phải sử dụng các tham số được đảm bảo để đáp ứng các tiêu chí này hoặc bạn gặp lỗi thời gian biên dịch. Trên đây là những hợp đồng rất đơn giản, bạn có thể chèn hầu hết mọi giả định hoặc yêu cầu về các biến hoặc ngoại lệ và mối quan hệ của chúng mà bạn có thể nghĩ ra và trình biên dịch sẽ kiểm tra xem mọi yêu cầu có được đảm bảo bởi một giả định hoặc điều gì đó có thể được đảm bảo hay không, có nguồn gốc từ các giả định. Đó là lý do tại sao tên bắt nguồn từ: Callee đưa ra yêu cầu , người gọi đảm bảo rằng những điều này được đáp ứng - giống như trong hợp đồng kinh doanh.

P(x1,x2,...,xn)nPĐược sử dụng. Từ phía CS, hai điều đó là những phần quan trọng của quy trình - việc tạo ra các điều kiện xác minh là khó khăn và SMT là một vấn đề hoàn chỉnh hoặc không thể giải quyết được, tùy thuộc vào các lý thuyết được xem xét. Thậm chí còn có một cuộc cạnh tranh cho người giải quyết SMT, vì vậy chắc chắn có một số nghiên cứu về điều này. Ngoài ra, có các cách tiếp cận khác để sử dụng SMT để xác minh chính thức như liệt kê không gian nhà nước, kiểm tra mô hình biểu tượng, kiểm tra mô hình giới hạn và nhiều phương pháp khác cũng đang được nghiên cứu, mặc dù, hiện tại, SMT là phương pháp "hiện đại" nhất.

Về giới hạn của ý tưởng chung:

  • Như đã nói trước đây, việc chứng minh tính đúng đắn của chương trình là một vấn đề khó tính toán, do đó, có thể việc kiểm tra thời gian biên dịch chương trình với các hợp đồng (hoặc một dạng đặc tả khác) thực sự mất nhiều thời gian hoặc thậm chí có thể là không thể. Áp dụng heuristic hoạt động tốt hầu hết thời gian là cách tốt nhất có thể làm về nó.
  • Bạn càng xác định rõ về chương trình của mình, khả năng có lỗi trong chính đặc tả càng cao . Điều này có thể dẫn đến kết quả dương tính giả (kiểm tra thời gian biên dịch thất bại mặc dù mọi thứ đều không có lỗi) hoặc ấn tượng sai về sự an toàn, mặc dù chương trình của bạn vẫn có lỗi.
  • Viết hợp đồng hoặc thông số kỹ thuật là công việc thực sự tẻ nhạt và hầu hết các lập trình viên quá lười biếng để làm điều đó. Hãy thử viết một chương trình C # với các hợp đồng mã ở khắp mọi nơi, sau một thời gian bạn sẽ nghĩ "thôi nào, điều này có thực sự cần thiết không?". Đó là lý do tại sao xác minh chính thức thường chỉ được sử dụng cho thiết kế phần cứng và các hệ thống quan trọng an toàn, như phần mềm điều khiển máy bay hoặc tự động.

Một điều đáng nói cuối cùng không phù hợp với lời giải thích ở trên là một lĩnh vực gọi là "Lý thuyết phức tạp tiềm ẩn", ví dụ như bài viết này . Nó nhằm mục đích mô tả các ngôn ngữ lập trình trong đó mỗi chương trình bạn có thể viết rơi vào một lớp phức tạp cụ thể, ví dụ P. Trong một ngôn ngữ như vậy, mỗi chương trình bạn viết sẽ tự động được "đảm bảo" là thời gian chạy đa thức, có thể được "kiểm tra" tại thời gian biên dịch bằng cách đơn giản biên dịch chương trình. Tuy nhiên, tôi không biết bất kỳ kết quả có thể sử dụng thực tế nào của nghiên cứu này, nhưng tôi cũng không phải là một chuyên gia.


Không nên tạo các loại hoặc hợp đồng phụ thuộc từ sự kết hợp của (các) thử nghiệm ví dụ và mã chưa được mã hóa, đưa ra một "chiến lược" nhất định mà bạn có thể chọn tùy thuộc vào dự án của mình?
aoeu256
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.