Chính xác thì “IB” và “UB” có nghĩa là gì?


110

Tôi đã thấy các thuật ngữ "IB" và "UB" được sử dụng nhiều lần, đặc biệt là trong ngữ cảnh của C ++. Tôi đã thử googling chúng, nhưng rõ ràng những kết hợp hai chữ cái đó được sử dụng rất nhiều. : P

Vì vậy, tôi hỏi bạn ... họ có nghĩa là gì, khi họ nói như thể họ là một điều xấu?


5
Nếu bạn quyết định lùi các chỉnh sửa của người khác, vui lòng đảm bảo rằng chính tả, dấu câu và ngữ pháp của bạn hoàn hảo. Quay lại các chỉnh sửa là một cải tiến đáng kể so với văn bản gốc là vô nghĩa.
Robert Harvey

Câu trả lời:


139

IB: Hành vi do triển khai xác định. Tiêu chuẩn này phụ thuộc vào trình biên dịch / nền tảng cụ thể để xác định hành vi chính xác, nhưng yêu cầu nó phải được xác định.

Sử dụng hành vi do triển khai xác định có thể hữu ích, nhưng làm cho mã của bạn ít di động hơn.

UB: Hành vi không xác định. Tiêu chuẩn không chỉ định cách một chương trình gọi hành vi không xác định sẽ hoạt động. Còn được gọi là "quỷ mũi" vì về mặt lý thuyết nó có thể khiến quỷ bay ra khỏi mũi của bạn.

Sử dụng hành vi không xác định luôn là một ý tưởng tồi. Ngay cả khi nó có vẻ hoạt động đôi khi, bất kỳ thay đổi nào đối với môi trường, trình biên dịch hoặc nền tảng có thể làm hỏng mã của bạn một cách ngẫu nhiên.


11
Tôi vẫn đang chờ một con quỷ bay ra khỏi mũi ai đó vì sử dụng hành vi không xác định trong C ++. Tôi đoán nó sẽ xảy ra khi các trình biên dịch đầu tiên tuân thủ hoàn toàn tiêu chuẩn C ++ mới.
OregonGhost

4
@OregonGhost: Tôi đoán bạn đúng. Tôi đã thấy nó xảy ra với kỳ lân một vài lần, nhưng chưa bao giờ là ma quỷ.
Thomas

33
@OregonGhost - tiêu chuẩn không quy định một con quỷ phải có bao nhiêu sừng.
DVK

5
@Michael Burr: Tôi thích "bắt lửa" hơn. Nó rõ ràng là thảm khốc, và nó có ít nhất một bầu không khí mơ hồ về sự chính đáng (phần cứng máy tính đôi khi bốc cháy, phải thừa nhận là vì lý do phần cứng chứ không phải lỗi phần mềm trong trường hợp của bất kỳ hệ thống nào bạn đang đọc luồng này).
Steve Jessop

1
Thật buồn cười khi không ai trả lời câu hỏi này có danh tiếng ít hơn 30k.

19

Hành vi do triển khai xác định và Hành vi không xác định

Tiêu chuẩn C ++ rất cụ thể về ảnh hưởng của các cấu trúc khác nhau, và đặc biệt là bạn phải luôn lưu ý các loại rắc rối sau:

  • Hành vi không xác định có nghĩa là hoàn toàn không có đảm bảo nào được đưa ra. Mã có thể hoạt động, hoặc nó có thể đốt cháy ổ cứng của bạn hoặc khiến ma quỷ bay ra khỏi mũi bạn . Đối với ngôn ngữ C ++, hoàn toàn có thể xảy ra bất cứ điều gì. Về mặt thực tế, điều này thường có nghĩa là bạn có một lỗi không thể khôi phục. Nếu điều này xảy ra, bạn không thể thực sự tin tưởng bất cứ điều gì về ứng dụng của mình (bởi vì một trong những tác động của hành vi không xác định này có thể chỉ là làm xáo trộn bộ nhớ được sử dụng bởi phần còn lại của ứng dụng của bạn). Nó không bắt buộc phải nhất quán, vì vậy chạy chương trình hai lần có thể cho kết quả khác nhau. Nó có thể phụ thuộc vào các giai đoạn của mặt trăng, màu sắc của chiếc áo bạn đang mặc hoặc bất cứ điều gì khác.

  • Hành vi không xác định có nghĩa là chương trình phải làm điều gì đó lành mạnh và nhất quán, nhưng nó không bắt buộc phải ghi lại điều này.

  • Hành vi được xác định bởi triển khai tương tự như hành vi không xác định, nhưng cũng phải được ghi lại bởi người viết trình biên dịch. Một ví dụ về điều này là kết quả của a reinterpret_cast. thông thường , nó chỉ đơn giản là thay đổi kiểu của một con trỏ, mà không sửa đổi địa chỉ, nhưng ánh xạ thực sự được xác định bởi việc triển khai, vì vậy một trình biên dịch có thể ánh xạ tới một địa chỉ hoàn toàn khác, miễn là nó ghi lại lựa chọn này. Một ví dụ khác là kích thước của một int. Tiêu chuẩn C ++ không quan tâm nếu nó là 2, 4 hay 8 byte, nhưng nó phải được trình biên dịch ghi lại

Nhưng chung cho tất cả những điều này là chúng tốt nhất nên tránh. Khi có thể, hãy tuân thủ hành vi được chỉ định 100% bởi chính tiêu chuẩn C ++. Bằng cách đó, bạn được đảm bảo tính di động.

Bạn cũng thường phải dựa vào một số hành vi do triển khai xác định. Nó có thể không thể tránh khỏi, nhưng bạn vẫn nên chú ý đến nó và lưu ý rằng bạn đang dựa vào một cái gì đó có thể thay đổi giữa các trình biên dịch khác nhau.

Mặt khác, luôn luôn cần tránh những hành vi không xác định . Nói chung, bạn chỉ nên cho rằng nó làm cho chương trình của bạn bùng nổ theo cách này hay cách khác.


1
UB nên được tránh nếu bạn quan tâm đến tính di động . Một triển khai cụ thể có thể xác định điều gì sẽ xảy ra đối với hành vi không xác định cụ thể và trong một số trường hợp (đặc biệt là trình điều khiển thiết bị và hệ thống nhúng nhỏ hơn), bạn cần sử dụng những thứ đó.
Jerry Coffin

3
@Jerry: Không, nên tránh UB nếu nó hoàn toàn không được xác định . Nếu nền tảng / triển khai / thời gian chạy / trình biên dịch cung cấp thêm đảm bảo, thì bạn có thể dựa vào hành vi và mất tính di động. Nhưng sau đó nó không còn là không xác định nữa ... Tuy nhiên, hầu hết thời gian, bạn không có sự đảm bảo nào như vậy, và undefined chỉ là không xác định, và cần phải tránh bằng mọi giá.
jalf

"nhất quán" có thể là một mô tả sai lệch về hành vi không xác định. Nó phải phù hợp với ngữ cảnh chung của hoạt động, ví dụ: nếu một biểu thức có "giá trị không xác định" thì kết quả phải một giá trị, nếu bạn lưu trữ nó thì giá trị được lưu trữ sau đó phải so sánh với chính nó, v.v. Nhưng kết quả không xác định không cần phải nhất quán theo thời gian (cùng một đầu ra cho cùng một đầu vào nếu bạn chạy lại), hoặc thậm chí có thể xác định.
Steve Jessop

"không còn là hoàn toàn không được xác định" - nó chính xác là không được xác định theo tiêu chuẩn , và UB là một từ viết tắt có nghĩa là không được xác định theo tiêu chuẩn. Trong ví dụ của bạn, nó được xác định bằng cách triển khai. Đối với vấn đề đó, bạn có thể dựa vào hành vi không được xác định bởi tiêu chuẩn hoặc việc triển khai, nếu bạn đã kiểm tra mã đối tượng và không có kế hoạch biên dịch lại ;-)
Steve Jessop

"sau đó phải so sánh bằng chính nó". Hmm, trừ khi đó là NaN. Dù sao, nó phải có bất kỳ hành vi nào được yêu cầu thuộc loại của nó.
Steve Jessop

8
  • IB: là hành vi được xác định thực hiện - trình biên dịch phải ghi lại những gì nó thực hiện. Thực hiện một >>phép toán trên một giá trị âm là một ví dụ.

  • UB: hành vi không xác định - trình biên dịch có thể làm bất cứ điều gì, bao gồm cả việc đơn giản là gặp sự cố hoặc cho kết quả không thể đoán trước. Tham chiếu đến một con trỏ null thuộc loại này, nhưng cũng có những thứ tinh vi hơn như số học con trỏ nằm ngoài giới hạn của một đối tượng mảng.

Một thuật ngữ liên quan khác là 'hành vi không xác định'. Đây là loại giữa các hành vi được xác định và chưa được xác định thực thi. đối với hành vi không xác định, trình biên dịch phải làm điều gì đó theo tiêu chuẩn, nhưng chính xác những lựa chọn nào mà tiêu chuẩn đưa ra là tùy thuộc vào trình biên dịch và không cần phải xác định (hoặc thậm chí nhất quán). Những thứ như thứ tự đánh giá các biểu thức phụ thuộc loại này. Trình biên dịch có thể thực hiện những điều này theo bất kỳ thứ tự nào nó thích và có thể thực hiện theo cách khác nhau trong các bản dựng khác nhau hoặc thậm chí trong các lần chạy khác nhau của cùng một bản dựng (không chắc, nhưng được phép).


4

Phiên bản ngắn:

Hành vi do triển khai xác định (IB): Được lập trình chính xác nhưng không xác định *

Hành vi không xác định (UB): Được lập trình không chính xác (tức là lỗi !)

*) "không xác định" theo tiêu chuẩn ngôn ngữ có liên quan, nó tất nhiên sẽ xác định trên bất kỳ nền tảng cố định nào.


Nếu tiêu chuẩn chỉ ra rằng một hành động gọi ra Hành vi do Triển khai xác định, thì việc triển khai được yêu cầu để chỉ định một hành vi nhất quán do hành động đó tạo ra. Thật không may, không có loại hành vi nào mà việc triển khai sẽ được yêu cầu để chỉ rõ các hậu quả có thể xảy ra, nhưng sẽ không bắt buộc phải có bất kỳ hậu quả cụ thể nào xảy ra một cách nhất quán.
supercat

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.