Tại sao không sử dụng mã an toàn không được quản lý trong C #


10

Có một tùy chọn trong C # để thực thi mã không được kiểm tra. Nói chung, không nên làm như vậy, vì mã được quản lý an toàn hơn nhiều và nó khắc phục được rất nhiều vấn đề.

Tuy nhiên tôi tự hỏi, nếu bạn chắc chắn rằng mã của bạn sẽ không gây ra lỗi và bạn biết cách xử lý bộ nhớ thì tại sao (nếu bạn thích mã nhanh) hãy làm theo lời khuyên chung?

Tôi tự hỏi điều này vì tôi đã viết một chương trình cho một máy quay video, đòi hỏi một số thao tác bitmap cực kỳ nhanh. Tôi đã tự mình thực hiện một số thuật toán đồ họa nhanh và chúng hoạt động tuyệt vời trên bitmap bằng cách sử dụng mã không được quản lý.

Bây giờ tôi tự hỏi nói chung, nếu bạn chắc chắn rằng bạn không bị rò rỉ bộ nhớ hoặc có nguy cơ gặp sự cố, tại sao không sử dụng mã không được quản lý thường xuyên hơn?

PS nền tảng của tôi: Tôi đã tham gia vào thế giới lập trình này và tôi làm việc một mình (tôi làm như vậy trong một vài năm) và vì vậy tôi hy vọng câu hỏi thiết kế phần mềm này không có gì lạ. Tôi thực sự không có người khác ở ngoài đó như một giáo viên để hỏi những điều như vậy.


8
unsafecó nghĩa là "biết những gì bạn đang làm và cân nhắc lợi ích chống lại rủi ro." Tôi đã sử dụng unsafemột số lần và nó luôn dành cho một thứ gì đó rất cụ thể liên quan đến hiệu suất có thể được xử lý theo phương pháp riêng của nó. Tôi không sử dụng nó như một kỹ thuật lập trình chung, vì phần lớn thời gian lợi ích hiệu suất bổ sung không đáng để mất đi sự an toàn.
Robert Harvey

14
Tôi đã viết rất nhiều mã trong những năm đôi khi bị hỏng hoặc bị rò rỉ bộ nhớ, rằng tôi khá chắc chắn rằng đã không bị rò rỉ bộ nhớ hoặc có nguy cơ gặp sự cố.
whatsisname

1
Dưới đây là một unsafeví dụ về trường hợp sử dụng tốt : stackoverflow.com/q/11660127/102937
Robert Harvey

3
Tôi đoán mã bitmap của bạn vẫn còn lỗi, nhưng bạn không phát hiện ra chúng. Và ngay cả khi đó không phải là trường hợp, hãy đợi cho đến khi bạn phải thực hiện một số yêu cầu mới vào mã hiện có.
Doc Brown

1
Bởi vì ngay cả khi bạn chắc chắn mã của mình sẽ không gây ra lỗi, nó vẫn gây ra lỗi.
dùng253751

Câu trả lời:


27

Chà, chủ yếu là một câu ngạn ngữ tuổi

  • Đừng tối ưu hóa
  • (chỉ dành cho chuyên gia) Đừng tối ưu hóa

Nhưng thực sự tôi có thể nghĩ ra ba lý do chính để tránh mã không an toàn.

  1. Lỗi : Phần quan trọng trong câu hỏi của bạn là "nếu bạn chắc chắn mã của mình sẽ không gây ra lỗi". Chà, làm thế nào bạn có thể hoàn toàn chắc chắn? Bạn đã sử dụng một prover với phương thức chính thức đảm bảo mã của bạn chính xác? Một điều chắc chắn trong lập trình, và đó là bạn sẽ gặp lỗi. Khi bạn cất cánh an toàn, bạn cho phép loại bọ mới chui qua máng. Khi bạn để người thu gom rác chăm sóc bộ nhớ cho bạn, rất nhiều vấn đề sẽ biến mất.

  2. Không phải lúc nào cũng nhanh như bạn nghĩ : Điểm khác là: tùy thuộc vào vấn đề, mức tăng có thể không lớn. Mặc dù tôi dường như không thể tìm thấy chúng ngay bây giờ, tôi nhớ một nghiên cứu của Google so sánh tốc độ của Java, Scala, Go và C ++. Sau khi được tối ưu hóa xuống đất, dĩ nhiên C ++ đã nhanh hơn rất nhiều. Nhưng thuật toán được lập trình theo cách "thành ngữ" không thực sự nhanh hơn nhiều. Thành ngữ theo nghĩa là họ đã sử dụng cấu trúc và thành ngữ tiêu chuẩn (thùng chứa stl, không có vòng lặp không được kiểm soát, v.v.). Microsoft đã làm một thí nghiệm tương tự với C # và C ++. Raymond Chen, một trong những Kỹ sư hàng đầu của Microsoft, đã phải viết bản triển khai std :: string của riêng mình để đánh bại C #. (xem: http : //www.codinghorror.com/blog/2005/05/on-managed-code-performance-again.html) Với ít nỗ lực hơn, bạn đã có hiệu suất khá tốt trong mã được quản lý, do đó, nó thường không đáng để gặp rắc rối.

  3. Khả năng sử dụng lại : Mã không an toàn chỉ có thể được sử dụng trong môi trường tin cậy đầy đủ. Ví dụ, trong một máy chủ ASP.NET, bạn thường không thể sử dụng mã không an toàn, vì sẽ rất dễ để đưa ra lỗ hổng bằng cách tràn bộ đệm. Một ví dụ khác sẽ là clickonce. Hoặc nếu ứng dụng của bạn được truy cập từ chia sẻ mạng. Vì vậy, nếu bạn có kế hoạch sử dụng mã của mình trong nhiều tình huống triển khai, mã không an toàn sẽ ra khỏi trò chơi.

Về cơ bản: nó cau mày vì nó có thể đưa ra các lỗi không cần thiết, nó hoàn toàn không có lợi ích gì và nó làm giảm khả năng sử dụng lại mã của bạn.

Nhưng nếu kịch bản của bạn thực sự đòi hỏi nó cho hiệu năng (và bạn có dữ liệu để chứng minh điều đó), thì bạn là một lập trình viên có kinh nghiệm, biết cách xử lý bộ nhớ và mã của bạn sẽ được sử dụng trong một môi trường được kiểm soát, vậy thì chắc chắn, hãy tìm nó.


4

Theo một cách nào đó, mã không được quản lý là một hình thức thanh toán: bạn mua thực thi nhanh hơn với nỗ lực phát triển thêm. Thật vậy, mã không được quản lý đòi hỏi nhiều thời gian hơn để phát triển, gỡ lỗi và duy trì. Làm cho nó chính xác là một thách thức cho hầu hết những người tham gia. Theo một cách nào đó, điều này tương tự như lập trình trong lắp ráp: chắc chắn, bạn có thể tiết kiệm được nhiều năng lượng hơn từ CPU nếu bạn viết trong lắp ráp * , nhưng bạn "tốn" nhiều công sức hơn để đi theo con đường đó.

Đôi khi, sự khác biệt về thời gian phát triển là rất đáng kể - ngày thay vì giờ. Tuy nhiên, sự khác biệt về tốc độ thực hiện gần như không đáng kể. Đó là lý do tại sao việc phát triển mã không được quản lý được dành riêng cho các tình huống tương tự như tình huống mà bạn đã mô tả trong bài đăng của mình - được bản địa hóa, khép kín, triển khai các thuật toán đói tài nguyên, như xử lý âm thanh và video.

Về cơ bản, câu trả lời cho câu hỏi của bạn tương tự như câu trả lời tại sao mọi người không lái Ferrari: đó là một chiếc xe tốt hơn nhiều, phải không? (Un) may mắn thay, không phải ai cũng có đủ khả năng.


* Những tiến bộ trong vài thập kỷ qua trong công nghệ tối ưu hóa trong trình biên dịch đã thu hẹp khoảng cách này đến mức nó không còn là một đặt cược chắc chắn nữa.


0

Bởi vì "chắc chắn" về tính đúng đắn hoặc bất kỳ ràng buộc nào khác theo nghĩa toán học (tức là bạn có bằng chứng) là một vấn đề rất khó đối với các ngôn ngữ bắt buộc. Các chương trình thường có số lượng trạng thái cao đến mức không thể xác minh chúng ngay cả khi kiểm tra từng trạng thái có thể. Và tạo ra một bằng chứng mang tính xây dựng không phải là thứ bạn có thể tự động hóa.

Vì vậy, lý do là các bảo hiểm mà việc thực hiện được quản lý cung cấp thường xuyên nhất là cân nhắc quá mức hiệu suất nhỏ mà bạn sẽ nhận được với mã không an toàn. Tất nhiên, điều này phụ thuộc vào trường hợp sử dụng cụ thể, quá.


1
Tôi không nghĩ nó có liên quan gì đến sự chính xác hay đơn giản đối với lý do ..
Jimmy Hoffa

Không ai nói về một bằng chứng chính thức về tính đúng đắn.

1
Tôi chắc chắn bài viết của bạn bỏ lỡ vấn đề, nhưng tôi không đưa ra một bằng chứng chính thức. Tương tự như vậy, tôi có thể chắc chắn rằng chương trình của tôi là chính xác (ví dụ: sau khi thử nghiệm rộng rãi, gỡ lỗi và sử dụng trong thế giới thực kéo dài mà không có bất kỳ lỗi nào phát sinh) mà không cần chứng minh một lần và mãi mãi. Giải thích này gần với ý nghĩa của hầu hết mọi người khi họ nói "chắc chắn là đúng". Các phương thức chính thức là một mối quan tâm rất riêng và hoàn toàn không được xem xét cho hầu hết các nhà phát triển.

1
Tôi thấy không có câu hỏi như vậy. Câu hỏi, như tôi đã đọc, là về lý do tại sao lối thoát khỏi thế giới được quản lý không / không nên được sử dụng thường xuyên hơn (ngụ ý rằng mặc định cho mã được quản lý có ý nghĩa). Trong mọi trường hợp, nếu bạn muốn trả lời câu hỏi đó (bằng cách chỉ ra độ cứng của việc đảm bảo tính chính xác), bạn có thể làm như vậy mà không cần nói về sự đảm bảo chính xác , tuyệt đối . Câu trả lời của bạn bây giờ chỉ xoay quanh việc hoàn thành, bằng chứng âm thanh chính xác cho các ngôn ngữ bắt buộc. Nhưng đó là quá mức cần thiết, và tôi nghĩ rằng bằng chứng về C # được quản lý cũng khó (hoặc gần như).

1
@fish: Tôi có thể thấy những gì bạn đang nói. Có một mối tương quan giữa một cái gì đó khó chứng minh và một cái gì đó khó để lý giải. Nếu thật khó để chứng minh chính xác, thì có lẽ rất khó để chắc chắn rằng nó đúng.
Michael Shaw

0

Nói tóm lại, không có gì ngăn cản bạn thực hiện tất cả công việc đó và quản lý các bit và bu lông của chương trình trong môi trường C ++. Vì bạn khá chắc chắn rằng bạn có thể quản lý chính xác tất cả các vòng lặp bộ nhớ và rò rỉ mà không cần trình thu gom rác, bạn có thể làm điều đó trong C ++ :)

Ngược lại, C # có lợi thế cung cấp môi trường phát triển an toàn / được quản lý và đánh máy mạnh để chạy an toàn trong .NET framework.

Sự rút lui có thể có của mã không được quản lý lập trình là thời gian phát triển dài hơn, phân bổ thời gian để thử nghiệm chi tiết. Tất nhiên bạn sẽ đạt được tốc độ xử lý và kiểm soát nhiều hơn về cách phần mềm của bạn đang chạy.

Do đó, tùy chọn làm việc với mã không được quản lý trong .NET Framework bắt đầu từ 4.0 là một tùy chọn cho các trường hợp cạnh khi bạn chắc chắn rằng nó có thể mang lại cho bạn lợi ích khi không sử dụng nó ...


Aha thật thú vị khi bạn thấy tôi đến từ thế giới vi điều khiển và người ta thường viết c ++ đàng hoàng, có rất ít lỗi và thiết kế tốt phần mềm là điều quan trọng cần làm
user613326
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.