Ngôn ngữ lập trình an toàn là gì?


54

Ngôn ngữ lập trình an toàn (PL) đang trở nên phổ biến. Tôi tự hỏi định nghĩa chính thức của PL an toàn là gì. Ví dụ, C không an toàn, nhưng Java an toàn. Tôi nghi ngờ rằng tài sản của người dùng an toàn nên được áp dụng cho việc triển khai PL hơn là cho chính PL. Nếu vậy, hãy thảo luận về một định nghĩa về thực hiện PL an toàn. Những nỗ lực của riêng tôi để chính thức hóa khái niệm này đã dẫn đến một kết quả kỳ lạ, vì vậy tôi muốn nghe ý kiến ​​khác. Xin vui lòng, đừng nói rằng mọi PL đều có các lệnh không an toàn. Chúng ta luôn có thể có một tập hợp con an toàn.


Bình luận không dành cho thảo luận mở rộng; cuộc trò chuyện này đã được chuyển sang trò chuyện .
Gilles 'SO- ngừng trở nên xấu xa'

"Chúng tôi luôn có thể có một tập hợp con an toàn" Làm thế nào bạn có thể chắc chắn rằng ngôn ngữ kết quả vẫn là Turing-Complete? (đó là những gì thường có nghĩa là "ngôn ngữ lập trình")
effeffe

"Tài sản của Google an toàn nên được áp dụng cho việc triển khai PL chứ không phải cho chính PL" - bạn có thể gọi PL an toàn nếu việc triển khai an toàn của nó tồn tại.
Dmitry Grigoryev

Câu trả lời:


17

Khi chúng ta gọi là một ngôn ngữ “an toàn” trong một số tôn trọng , đó chính thức có nghĩa là có một bằng chứng cho thấy chương trình không tốt được hình thành trong các ngôn ngữ có thể làm điều gì đó chúng ta xem xét nguy hiểm. Từ "an toàn" cũng được sử dụng ít chính thức hơn, nhưng đó là những gì mọi người ở đây hiểu câu hỏi của bạn có nghĩa là gì. Có rất nhiều định nghĩa khác nhau về các thuộc tính mà chúng tôi muốn có một ngôn ngữ của chương trình An toàn trên mạng.

Một vài điều quan trọng là:

  • Định nghĩa về âm thanh của Andrew Wright và Matthias Felleisen về âm thanh kiểu Hồi giáo , được trích dẫn ở nhiều nơi (bao gồm cả Wikipedia) như một định nghĩa được chấp nhận về an toàn loại kiểu Hồi, và một bằng chứng năm 1994 của họ rằng một tập hợp con ML đáp ứng nó.

  • Michael Hicks liệt kê một số định nghĩa về an toàn bộ nhớ trên mạng ở đây . Một số là danh sách các loại lỗi không thể xảy ra và một số dựa trên việc coi con trỏ là khả năng. Java đảm bảo rằng không có lỗi nào trong số đó là có thể (trừ khi bạn sử dụng rõ ràng một tính năng được đánh dấu unsafe) bằng cách có trình thu gom rác quản lý tất cả các phân bổ và phân bổ. Rust đưa ra sự bảo đảm tương tự (một lần nữa, trừ khi bạn đánh dấu rõ ràng mã là unsafe), thông qua hệ thống kiểu affine của nó, yêu cầu một biến phải được sở hữu hoặc mượn trước khi được sử dụng nhiều nhất một lần.

  • Tương tự, mã an toàn luồng thường được định nghĩa là mã không thể biểu hiện một số loại lỗi nhất định liên quan đến luồng và bộ nhớ dùng chung, bao gồm cả các cuộc đua dữ liệu và khóa chết. Các thuộc tính này thường được thi hành ở cấp ngôn ngữ: Rust đảm bảo rằng các cuộc đua dữ liệu không thể xảy ra trong hệ thống loại của nó, C ++ đảm bảo rằng các std::shared_ptrcon trỏ thông minh của nó tới cùng một đối tượng trong nhiều luồng sẽ không xóa đối tượng sớm hoặc không xóa nó khi tham chiếu cuối cùng để nó bị phá hủy, C và C ++ cũng có atomiccác biến được tích hợp vào ngôn ngữ, với các hoạt động nguyên tử được đảm bảo để thực thi một số loại nhất quán bộ nhớ nếu được sử dụng đúng. MPI hạn chế giao tiếp giữa các quá trình với các thông báo rõ ràng và OpenMP có cú pháp để đảm bảo rằng quyền truy cập vào các biến từ các luồng khác nhau là an toàn.

  • Thuộc tính mà bộ nhớ sẽ không bao giờ rò rỉ thường được gọi là không gian an toàn. Thu gom rác tự động là một tính năng ngôn ngữ để đảm bảo điều này.

  • Nhiều ngôn ngữ đảm bảo rằng các hoạt động của nó sẽ có kết quả được xác định rõ và các chương trình của nó sẽ được xử lý tốt. Như supercat đã đưa ra một ví dụ ở trên, C thực hiện điều này cho số học không dấu (được bảo đảm để bọc an toàn) nhưng không ký số học (trong đó tràn được phép gây ra các lỗi tùy ý, vì C cần hỗ trợ các CPU thực hiện những điều khác biệt khi ký số học tràn ra), nhưng sau đó ngôn ngữ đôi khi âm thầm chuyển đổi số lượng không dấu thành số lượng đã ký.

  • Các ngôn ngữ chức năng có một số lượng lớn các bất biến mà bất kỳ chương trình được hình thành tốt nào cũng được đảm bảo duy trì, ví dụ, các hàm thuần túy không thể gây ra tác dụng phụ. Những thứ này có thể hoặc không thể được mô tả là an toàn.

  • Một số ngôn ngữ, như SPARK hoặc OCaml, được thiết kế để tạo điều kiện chứng minh tính đúng đắn của chương trình. Điều này có thể hoặc không thể được mô tả là một cách an toàn.

  • Bằng chứng là một hệ thống không thể vi phạm một mô hình bảo mật chính thức (do đó, quip, bất kỳ hệ thống nào có thể bảo mật chắc chắn đều không thể.


1
Điều này có thể hoặc không thể được mô tả là một cách an toàn. Bạn vui lòng giải thích điều này một chút? Bạn có ý nghĩa gì bởi "từ lỗi"?
scaaahu

2
@scaaahu Đây là một ví dụ về một trang web đề cập đến phần mềm chính thức được chứng minh là chính xác, an toàn có thể chứng minh được. Từ ngữ cảnh này, nó đề cập đến phần mềm để ngăn máy bay va chạm, vì vậy nó có nghĩa là an toàn khi va chạm.
Davislor

1
Tôi chấp nhận câu trả lời này vì nó liệt kê các loại an toàn. Loại mà tôi có trong tâm trí là an toàn bộ nhớ.
beroal

Trong khi câu trả lời này liệt kê một số liên kết hữu ích và rất nhiều ví dụ, hầu hết chúng đều hoàn toàn sai lầm. Bộ sưu tập rác đảm bảo rằng bộ nhớ sẽ không bao giờ bị rò rỉ hoặc không sử dụng các khối "không an toàn" tự động mang lại cho bạn sự an toàn hoặc tràn tràn được ký là Hành vi không xác định vì trình biên dịch cần phải hỗ trợ một số CPU kỳ lạ? Và chỉ một từ ngắn gọn cho Ada / SPARK, đây là ngôn ngữ duy nhất được coi là an toàn nghiêm túc.
VTT

93

Không có định nghĩa chính thức về "ngôn ngữ lập trình an toàn"; đó là một khái niệm không chính thức. Thay vào đó, các ngôn ngữ tuyên bố cung cấp sự an toàn thường cung cấp một tuyên bố chính thức chính xác về loại an toàn nào đang được yêu cầu / bảo đảm / cung cấp. Ví dụ, ngôn ngữ có thể cung cấp loại an toàn, an toàn bộ nhớ hoặc một số bảo đảm tương tự khác.


13
Là một addeumdum, nếu chúng ta nói về C vs Java như bài đăng của OP: đó là sự an toàn bộ nhớ được đảm bảo trong Java và không phải trong C. Loại an toàn được cung cấp bởi cả hai theo cách riêng của họ. (Vâng, rất nhiều người đọc cái này đã biết điều đó, nhưng có lẽ một số người không biết).
Walfrat

17
@Walfrat Đó là một phần của nó. Java cũng không có hành vi không xác định, đó là điều mà chúng tôi mong đợi về một ngôn ngữ tự gọi là 'an toàn'. Đối với các hệ thống loại, tôi không nghĩ rằng một hệ thống loại tĩnh mạnh là những gì mọi người có nghĩa là 'an toàn'. Nói chung, các ngôn ngữ được gõ động như Python nói chung là 'an toàn'.
Max Barraclough

2
Định nghĩa của tôi về an toàn loại là kiểm tra biên dịch xử lý đó. Đó có thể không phải là định nghĩa chính thức. Lưu ý rằng tôi đã nói "loại an toàn", không phải "an toàn". Đối với tôi, ngôn ngữ "an toàn" đề cập đến "định nghĩa" của tôi về "loại an toàn và bộ nhớ" và tôi nghĩ nó có thể là ngôn ngữ phổ biến nhất. Tất nhiên tôi không nói về một số cạm bẫy như con trỏ phản chiếu / void trong C mà quá trình biên dịch không thể xử lý. Một định nghĩa khác về an toàn là chương trình không gặp sự cố với lỗi phân đoạn như con trỏ đơn vị hóa trong C. Những thứ như thế thường được cấp trong Python và Java.
Walfrat

7
@Walfrat Tất cả những gì có được bạn mặc dù là một ngôn ngữ mà cú pháp được xác định rõ. Điều đó không đảm bảo rằng việc thực thi được xác định rõ - và số lần tôi gặp sự cố JRE, tôi có thể nói với bạn rằng đây là một hệ thống không "an toàn". Mặt khác, trong C, MISRA đã đưa công việc vào việc tránh các hành vi không xác định để có được một tập hợp con an toàn hơn của ngôn ngữ và việc biên dịch C thành trình biên dịch được xác định rõ hơn nhiều. Vì vậy, nó phụ thuộc vào những gì bạn cho là "an toàn".
Graham

5
@MaxBarraclough - "Java cũng không có hành vi không xác định" - Java không có hành vi không xác định theo nghĩa được sử dụng trong các đặc tả C trong định nghĩa ngôn ngữ (mặc dù nó cho phép một số mã tạo ra các giá trị không có một giá trị được xác định trước, ví dụ như truy cập một biến đang được sửa đổi trong một luồng khác hoặc bằng cách truy cập vào một doublehoặc longtrong khi nó đang được sửa đổi trong một luồng khác, điều đó không đảm bảo không tạo ra một nửa của một giá trị được trộn lẫn theo một cách không xác định với một nửa khác) nhưng đặc tả API tuy nhiên có hành vi không xác định trong một số trường hợp.
Jules

41

Nếu bạn có thể chạm tay vào một bản sao các loại và ngôn ngữ lập trình của Benjamin Pierce , trong phần giới thiệu, anh ta có một cái nhìn tổng quan tốt về các quan điểm khác nhau về thuật ngữ "ngôn ngữ an toàn".

Một cách giải thích được đề xuất về thuật ngữ mà bạn có thể thấy thú vị là:

Ngôn ngữ an toàn được định nghĩa hoàn toàn theo hướng dẫn của lập trình viên. Hãy để định nghĩa của ngôn ngữ là tập hợp những điều mà lập trình viên cần hiểu để dự đoán hành vi của mọi chương trình trong ngôn ngữ. Sau đó, hướng dẫn sử dụng cho một ngôn ngữ như C không tạo thành định nghĩa, vì hành vi của một số chương trình (ví dụ: các chương trình liên quan đến truy cập mảng không được kiểm soát hoặc số học con trỏ) không thể dự đoán được mà không biết chi tiết về cách trình biên dịch C cụ thể đưa ra các cấu trúc trong bộ nhớ , v.v., và cùng một chương trình có thể có các hành vi khá khác nhau khi được thực hiện bởi các trình biên dịch khác nhau.

Vì vậy, tôi sẽ do dự khi sử dụng thuật ngữ "không an toàn" để chỉ việc triển khai ngôn ngữ lập trình. Nếu một thuật ngữ không xác định trong ngôn ngữ tạo ra hành vi khác nhau trong các triển khai khác nhau, một trong những triển khai có thể là hành vi sản phẩm có thể được mong đợi hơn, nhưng tôi sẽ không gọi đó là "an toàn".


7
Vấn đề dừng tất nhiên nói rằng bất kể ngôn ngữ, sẽ luôn có các chương trình mà hành vi của chúng không thể dự đoán được từ định nghĩa ngôn ngữ. Vì vậy, bất kỳ định nghĩa nào xoay quanh "dự đoán hành vi của mọi chương trình trong ngôn ngữ" về cơ bản là thiếu sót đối với bất kỳ ngôn ngữ hoàn chỉnh Turing nào.
MSalters

15
@MSalters Đây là một sự hiểu lầm phổ biến về vấn đề tạm dừng. Tính không ổn định của vấn đề tạm dừng ngụ ý rằng không thể rút ra một cách máy móc hành vi của một chương trình tùy ý trong một ngôn ngữ hoàn chỉnh Turing. Nhưng có thể là đối với bất kỳ chương trình nhất định , hành vi có thể dự đoán được. Chỉ là bạn không thể tạo ra một chương trình máy tính đưa ra dự đoán này.
Gilles 'SO- đừng trở nên xấu xa'

7
@Giles: Không phải vậy. Giả sử tồn tại một bằng chứng về việc không chấm dứt cho mọi chương trình không kết thúc. Sau đó, bạn có thể liệt kê các bằng chứng về việc không chấm dứt để tìm xem liệu một chương trình nhất định có dừng lại hay không. Vì vậy, vấn đề tạm dừng là quyết định. Mâu thuẫn. Do đó, một số chương trình không kết thúc không chứng minh được là không kết thúc.
Kevin

9
@Gilles: Tôi hoàn toàn nhận thức được thực tế rằng nhiều chương trình được chứng minh tầm thường để tạm dừng hoặc không. Nhưng tuyên bố ở đây là nghĩa đen về hành vi của mọi chương trình. Bằng chứng của Định lý Dừng cho thấy rằng tồn tại ít nhất một chương trình không đúng. Nó chỉ là một bằng chứng không mang tính xây dựng, nó sẽ không cho bạn chương trình là undecidable.
MSalters

8
@MSalters Tôi nghĩ rằng bit ngụ ý là tuyên bố nói về hành vi quy mô nhỏ của chương trình, chứ không phải là hành vi nổi lên, quy mô lớn. Ví dụ, lấy phỏng đoán Collatz . Các bước riêng lẻ của thuật toán rất đơn giản và được xác định rõ ràng, nhưng hành vi mới nổi (có bao nhiêu lần lặp cho đến khi dừng lại và nếu nó hoàn toàn không xảy ra), là bất cứ điều gì ngoài. - "Dự đoán" đang được sử dụng không chính thức ở đây. Nó có thể được viết tốt hơn là "biết bất kỳ tuyên bố nào được đưa ra trong một chương trình tùy ý sẽ thực thi."
RM

18

An toàn không phải là nhị phân, nó là một sự liên tục .

Nói một cách không chính thức, sự an toàn có nghĩa là sự phản đối các lỗi, 2 điều thường được nhắc đến nhất là:

  • An toàn bộ nhớ: ngôn ngữ và cách triển khai của nó ngăn ngừa một loạt các lỗi liên quan đến bộ nhớ, chẳng hạn như truy cập sau khi sử dụng, miễn phí hai lần, ngoài giới hạn, ...
  • Loại an toàn: ngôn ngữ và cách triển khai của nó ngăn ngừa nhiều loại lỗi liên quan đến loại như phôi không được kiểm tra, ...

Đó không phải các loại lỗi duy nhất mà ngôn ngữ ngăn chặn, tự do chạy đua dữ liệu hoặc tự do bế tắc là điều đáng mong muốn, bằng chứng về tính chính xác là khá ngọt ngào, v.v ...

Tuy nhiên, các chương trình đơn giản không chính xác hiếm khi được coi là "không an toàn" (chỉ có lỗi) và thuật ngữ an toàn thường được dành riêng cho các đảm bảo ảnh hưởng đến khả năng suy luận về chương trình của chúng tôi . Do đó, C, C ++ hoặc Go, có Hành vi không xác định, không an toàn.

Và tất nhiên, có những ngôn ngữ có các tập hợp con không an toàn (Java, Rust, ...) nhằm phân định một cách có chủ đích các khu vực nơi nhà phát triển chịu trách nhiệm duy trì các đảm bảo ngôn ngữ và trình biên dịch ở chế độ "rảnh tay". Các ngôn ngữ nói chung vẫn được gọi là an toàn , mặc dù lối thoát này, một định nghĩa thực dụng.


7
Tôi muốn nói đó là một mạng tinh thể.
PatJ

1
Hầu hết các triển khai ngôn ngữ lập trình đều có các tính năng không an toàn (ví dụ: Obj.magictrong Ocaml). Và trong thực tế, những thứ này thực sự cần thiết
Basile Starynkevitch

4
@BasileStarynkevitch: Thật vậy. Tôi nghĩ rằng bất kỳ ngôn ngữ nào có FFI nhất thiết phải chứa một số mức độ không an toàn, vì việc gọi hàm C sẽ yêu cầu "đánh dấu" các đối tượng của GC và đảm bảo rằng các chữ ký ở cả hai bên khớp với nhau.
Matthieu M.

15

Mặc dù tôi không đồng ý với câu trả lời của DW, tôi nghĩ rằng nó để lại một phần của "an toàn" không được giải quyết.

Theo ghi nhận, có nhiều loại an toàn được thúc đẩy. Tôi tin rằng thật tốt khi hiểu tại sao có nhiều khái niệm. Mỗi khái niệm được liên kết với ý tưởng rằng các chương trình phải chịu đặc biệt là từ một loại lỗi nhất định và các lập trình viên sẽ không thể tạo ra loại lỗi cụ thể này nếu ngôn ngữ chặn lập trình viên làm như vậy.

Do đó, cần lưu ý rằng các khái niệm khác nhau này do đó có các lớp lỗi khác nhau và các lớp này không loại trừ lẫn nhau cũng như các lớp này bao gồm tất cả các dạng lỗi. Chỉ cần lấy 2 ví dụ của DW, câu hỏi liệu một vị trí bộ nhớ nhất định có giữ một đối tượng nhất định hay không là cả một câu hỏi về an toàn loại và an toàn bộ nhớ.

Một chỉ trích nữa về "ngôn ngữ an toàn" xuất phát từ quan sát rằng việc cấm một số cấu trúc được coi là nguy hiểm khiến lập trình viên cần phải đưa ra các giải pháp thay thế. Theo kinh nghiệm, an toàn đạt được tốt hơn bởi các thư viện tốt. sử dụng mã đã được kiểm tra tại hiện trường giúp bạn tránh khỏi các lỗi mới.


10
Nó khá lạc đề đối với trang web này, vì công nghệ phần mềm không thực sự là một môn khoa học, nhưng tôi không đồng ý với tuyên bố thực nghiệm của bạn. Sử dụng các thư viện tốt sẽ không giúp bạn tiết kiệm ngôn ngữ không an toàn vì bạn không được bảo vệ khỏi việc sử dụng sai. Ngôn ngữ an toàn cho phép bạn nhận được nhiều bảo đảm hơn từ tác giả thư viện và cho phép bạn có thêm sự đảm bảo rằng bạn đang sử dụng chúng một cách chính xác.
Gilles 'SO- ngừng trở nên xấu xa'

3
Tôi với MSalters về điều này. - "Ngôn ngữ an toàn cho phép bạn nhận được nhiều bảo đảm hơn từ tác giả thư viện và cho phép bạn có thêm sự đảm bảo rằng bạn đang sử dụng chúng một cách chính xác." Đây là một sequitur cho tất cả các mục đích thực tế.
Thuyền trưởng Hươu cao cổ

9

Một điểm khác biệt cơ bản giữa C và Java là nếu một người tránh được một số tính năng dễ nhận biết nhất định của Java (ví dụ: trong các Unsafekhông gian tên), mọi hành động có thể xảy ra có thể xảy ra - bao gồm cả những lỗi "sai lầm" - sẽ có phạm vi kết quả có thể hạn chế . Mặc dù điều này giới hạn những gì người ta có thể làm trong Java - ít nhất là không sử dụng Unsafekhông gian tên, nhưng nó cũng giúp hạn chế thiệt hại có thể gây ra bởi một chương trình sai lầm, hoặc - quan trọng hơn - bởi một chương trình sẽ xử lý chính xác các tập tin hợp lệ nhưng không được bảo vệ đặc biệt chống lại các tập tin sai.

Theo truyền thống, trình biên dịch C sẽ xử lý nhiều hành động theo kiểu được định nghĩa chuẩn trong các trường hợp "bình thường", trong khi xử lý nhiều trường hợp góc "theo cách đặc trưng của môi trường". Nếu một người đang sử dụng CPU sẽ tắt và bắt lửa nếu xảy ra tràn số và muốn tránh CPU bắt lửa, người ta sẽ cần phải viết mã để tránh tràn số. Tuy nhiên, nếu một người đang sử dụng CPU có thể cắt giảm hoàn toàn các giá trị theo kiểu bổ sung hai, thì người ta không phải tránh tràn ra trong trường hợp việc cắt ngắn như vậy sẽ dẫn đến hành vi chấp nhận được.

Modern C đưa mọi thứ đi xa hơn: ngay cả khi một người đang nhắm mục tiêu một nền tảng sẽ xác định một cách tự nhiên một hành vi cho một thứ gì đó như tràn số, trong đó Tiêu chuẩn sẽ không áp đặt yêu cầu, việc tràn vào một phần của chương trình có thể ảnh hưởng đến hành vi của các phần khác của chương trình theo kiểu tùy tiện không bị ràng buộc bởi quy luật thời gian và nhân quả. Ví dụ, hãy xem xét một cái gì đó như:

 uint32_t test(uint16_t x)
 {
   if (x < 50000) foo(x);
   return x*x; // Note x will promote to "int" if that type is >16 bits.
 }

Trình biên dịch C "hiện đại" được cung cấp giống như ở trên có thể kết luận rằng vì tính toán của x * x sẽ tràn nếu x lớn hơn 46340, nó có thể thực hiện lệnh gọi "foo" vô điều kiện. Lưu ý rằng ngay cả khi chương trình kết thúc một cách bất thường nếu x nằm ngoài phạm vi hoặc hàm có trả về bất kỳ giá trị nào trong các trường hợp đó, việc gọi foo () với x ngoài phạm vi có thể gây ra thiệt hại vượt xa một trong những khả năng đó C truyền thống sẽ không cung cấp bất kỳ thiết bị an toàn nào ngoài những gì lập trình viên và nền tảng cơ bản được cung cấp, nhưng sẽ cho phép thiết bị an toàn hạn chế thiệt hại từ các tình huống bất ngờ. Modern C sẽ bỏ qua mọi thiết bị an toàn không hiệu quả 100% trong việc kiểm soát mọi thứ.


3
@DavidThornley: Có lẽ ví dụ của tôi quá tinh tế. Nếu intlà 32 bit, sau đó xsẽ được thăng cấp để ký int. Đánh giá từ các lý do, các tác giả của Tiêu chuẩn dự kiến triển khai không lạ sẽ đối xử với loại unsigned trong thời trang tương đương bên ngoài của một số trường hợp cụ thể có chữ ký và, nhưng gcc đôi khi "tối ưu hóa" theo những cách mà phá vỡ nếu một uint16_tbằng uint16_tnhân mang lại một kết quả vượt INT_MAX , ngay cả khi kết quả đang được sử dụng làm giá trị không dấu.
supercat

4
Ví dụ tốt. Đây là một lý do tại sao chúng ta nên luôn luôn biên dịch (trên GCC hoặc Clang) -Wconversion.
Davislor

2
@Davislor: Ah, tôi chỉ nhận thấy rằng godbolt đảo ngược thứ tự các phiên bản trình biên dịch được liệt kê, vì vậy việc chọn phiên bản gcc cuối cùng trong danh sách mang lại kết quả mới nhất thay vì sớm nhất. Tôi không nghĩ rằng cảnh báo là đặc biệt hữu ích vì nó dễ bị gắn cờ với nhiều tình huống return x+1;không nên có vấn đề và việc đưa kết quả lên uint32_t sẽ bóp nghẹt thông báo mà không khắc phục được sự cố.
supercat

2
@supercat Loại bỏ các bài kiểm tra là vô nghĩa nếu trình biên dịch được yêu cầu đưa các bài kiểm tra trở lại ở một nơi khác.
dùng253751

3
@immibis: Chỉ thị "giả định đã kiểm tra" có thể cho phép trình biên dịch thay thế nhiều kiểm tra hoặc kiểm tra sẽ được thực hiện nhiều lần trong một vòng lặp, với một thử nghiệm duy nhất có thể được đưa ra bên ngoài một vòng lặp. Điều đó tốt hơn là yêu cầu các lập trình viên thêm các kiểm tra không cần b trong mã máy để chương trình đáp ứng yêu cầu, nhằm mục đích đảm bảo trình biên dịch không "tối ưu hóa" các kiểm tra cần thiết để đáp ứng yêu cầu.
supercat

7

Có một vài lớp chính xác trong một ngôn ngữ. Theo thứ tự tăng trừu tượng:

  • Rất ít chương trình không có lỗi (chỉ những chương trình có thể chứng minh tính đúng). Do đó, những người khác đã đề cập rằng ngăn chặn lỗi là khía cạnh an toàn cụ thể nhất. Các ngôn ngữ chạy trong một máy ảo như Java và .net thường an toàn hơn về mặt này: Các lỗi chương trình thường bị chặn và xử lý theo cách được xác định. 1
  • Ở cấp độ tiếp theo, các lỗi được phát hiện tại thời gian biên dịch thay vì tại thời gian chạy giúp ngôn ngữ an toàn hơn. Một chương trình đúng về mặt cú pháp cũng phải đúng về mặt ngữ nghĩa càng nhiều càng tốt. Tất nhiên trình biên dịch không thể biết bức tranh lớn, vì vậy điều này liên quan đến mức độ chi tiết. Các kiểu dữ liệu mạnh và biểu cảm là một khía cạnh của sự an toàn ở cấp độ này. Người ta có thể nói ngôn ngữ sẽ gây khó khăn cho việc mắc một số loại lỗi nhất định(lỗi loại, truy cập ngoài ràng buộc, các biến chưa được khởi tạo, v.v.). Thông tin loại thời gian chạy như mảng mang thông tin độ dài tránh lỗi. Tôi đã lập trình Ada 83 ở trường đại học và thấy rằng một chương trình Ada biên dịch thường có lẽ có một lỗi có độ lớn ít hơn so với chương trình C tương ứng. Chỉ cần sử dụng khả năng của Ada để xác định loại số nguyên không thể gán được mà không chuyển đổi rõ ràng: Toàn bộ tàu không gian đã bị hỏng vì chân và mét bị nhầm lẫn, điều mà người ta có thể tránh một cách tầm thường với Ada.

  • Ở cấp độ tiếp theo, ngôn ngữ nên cung cấp các phương tiện để tránh mã soạn sẵn. Nếu bạn phải viết các thùng chứa của riêng bạn, hoặc sắp xếp chúng, hoặc ghép chúng, hoặc nếu bạn phải viết riêng của string::trim()bạn, bạn sẽ phạm sai lầm. Vì mức độ trừu tượng tăng lên, tiêu chí này liên quan đến ngôn ngữ phù hợp cũng như thư viện chuẩn của ngôn ngữ.

  • Ngày nay, ngôn ngữ nên cung cấp phương tiện để lập trình đồng thời ở cấp độ ngôn ngữ. Đồng thời là khó để có được đúng và có lẽ không thể làm chính xác mà không có hỗ trợ ngôn ngữ.

  • Ngôn ngữ nên cung cấp phương tiện cho việc mô đun hóa và hợp tác. Các loại mạnh mẽ, công phu, do người dùng xác định từ bên trên giúp tạo API biểu cảm.

Phần nào định nghĩa ngôn ngữ nên dễ hiểu; ngôn ngữ và thư viện nên được ghi chép tốt. Tài liệu xấu hoặc thiếu dẫn đến các chương trình xấu và sai.


1 Nhưng vì thông thường tính chính xác của máy ảo không thể được chứng minh nên các ngôn ngữ có thể hơi nghịch lý khi không phù hợp với các yêu cầu an toàn rất nghiêm ngặt.


1
+1 Đối với lớp rõ ràng bằng cách giải thích lớp. Một câu hỏi cho bạn, tàu không gian toàn bộ đã bị rơi vì chân và mét bị nhầm lẫn, điều mà người ta có thể tránh một cách tầm thường với Ada. , bạn đang nói về Mars thăm dò bị mất do lỗi toán học đơn giản ? Bạn có tình cờ biết ngôn ngữ họ đang sử dụng cho con tàu không gian đó không?
scaaahu

2
@scaaahu Vâng, tôi nghĩ rằng tôi đã đề cập đến điều đó. Không, tôi không biết ngôn ngữ. Trên thực tế, đọc báo cáo, có vẻ như dữ liệu được gửi bởi đầu dò đã được xử lý bằng phần mềm trên trái đất tạo ra một tệp dữ liệu sau đó được sử dụng để xác định mức lực đẩy. Gõ ngôn ngữ đơn giản không được áp dụng trong kịch bản này. Btw., Họ có nhiều vấn đề với phần mềm mặt đất và định dạng tệp dữ liệu, một sự nhầm lẫn đã ngăn chặn sự phát hiện sớm của vấn đề. Vì vậy, câu chuyện không phải là một cuộc tranh luận trực tiếp cho việc đánh máy mạnh mẽ nhưng vẫn là một câu chuyện cảnh báo.
Peter - Tái lập Monica

1

Xin vui lòng, đừng nói rằng mọi PL đều có các lệnh không an toàn. Chúng ta luôn có thể có một tập hợp con an toàn.

Mọi ngôn ngữ tôi biết đều có cách viết các chương trình bất hợp pháp có thể (biên dịch và) chạy. Và mọi ngôn ngữ mà tôi biết đều có một tập hợp con an toàn. Vì vậy, câu hỏi của bạn thực sự là gì?


An toàn là đa chiều và chủ quan.

Một số ngôn ngữ có nhiều hoạt động "không an toàn". Những người khác có ít hoạt động như vậy. Trong một số ngôn ngữ, cách mặc định để làm một cái gì đó vốn không an toàn. Trong những người khác, cách mặc định là an toàn. Trong một số ngôn ngữ, có một tập hợp con "không an toàn" rõ ràng. Trong các ngôn ngữ khác, không có tập hợp con như vậy cả.

Trong một số ngôn ngữ, "an toàn" chỉ dành riêng cho an toàn bộ nhớ - một dịch vụ được cung cấp bởi thư viện tiêu chuẩn và / hoặc thời gian chạy nơi vi phạm truy cập bộ nhớ được thực hiện khó khăn hoặc không thể. Trong các ngôn ngữ khác, "an toàn" rõ ràng bao gồm an toàn luồng. Trong các ngôn ngữ khác, "an toàn" đề cập đến sự đảm bảo rằng chương trình sẽ không gặp sự cố (một yêu cầu bao gồm không cho phép các trường hợp ngoại lệ chưa được khai thác dưới bất kỳ hình thức nào). Cuối cùng, trong nhiều ngôn ngữ, "an toàn" đề cập đến an toàn loại - nếu hệ thống loại nhất quán theo một số cách nhất định, nó được gọi là "âm thanh" (tình cờ, Java và C # không có hệ thống loại âm thanh hoàn toàn).

Và trong một số ngôn ngữ, tất cả các ý nghĩa khác nhau của "an toàn" được coi là tập hợp con của an toàn loại (ví dụ: Rust và Pony đạt được an toàn luồng thông qua các thuộc tính của hệ thống loại).


-1

Câu trả lời này rộng hơn một chút. Các từ an toàn và an toàn trong những thập kỷ gần đây đã bị cắt xén bởi một số bộ phận định hướng chính trị của xã hội nói tiếng Anh, do đó việc sử dụng phổ biến của chúng gần như không có định nghĩa. Tuy nhiên, đối với các đối tượng kỹ thuật, tôi vẫn quay lại định nghĩa "an toàn" và "an toàn" là: một thiết bị ngăn chặn việc sử dụng vô ý một thứ gì đó hoặc khiến việc sử dụng vô tình trở nên khó khăn hơn và tình trạng được bảo vệ bởi một thiết bị như vậy .
Vì vậy, một ngôn ngữ an toàn có một số thiết bị để hạn chế một loại lỗi cụ thể. Tất nhiên các giới hạn đi kèm với sự bất tiện hoặc thậm chí không có khả năng trong một số trường hợp và điều đó không có nghĩa là các ngôn ngữ "không an toàn" sẽ dẫn đến lỗi. ví dụ: tôi không có nút chai an toàn trên dĩa của mình và đã quản lý trong nhiều thập kỷ, mà không cần nỗ lực nhiều, để tránh đâm vào mắt trong khi ăn. Chắc chắn ít nỗ lực hơn so với việc sử dụng nút chai. Vì vậy, An toàn đi kèm với một số chi phí mà nó phải được đánh giá. (nút chai là một tham chiếu đến một nhân vật Steve Martin)

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.