2013-01-03 28 views
19

Cả Java và C#, và có thể là nhiều ngôn ngữ khác nữa, có một lớp ngoại lệ được xác định trước được ném khi tham số null được sử dụng ở nơi nó không được sử dụng. Có bất cứ điều gì tương tự trong C + +? Nếu không, có một ngoại lệ được xác định trước khác mà tôi có thể sử dụng hay tôi nên định nghĩa một ngoại lệ của riêng mình không?Có tương đương C++ của NullPointerException

+9

Lỗi phân đoạn. – kmkaplan

+0

FTR, trong C# bạn không sử dụng NullReferenceExceptions cho bất cứ điều gì trừ khi bạn muốn bị đâm bởi đồng đội của bạn. –

+0

Trong C# tôi sử dụng một ArgumentNullException và đồng đội của tôi luôn luôn tốt đẹp với tôi. –

Trả lời

20

Dereferencing con trỏ NULL là hành vi không xác định trong C++ - có nghĩa là mã có thể xuất hiện để hoạt động. Một ngoại lệ không được đảm bảo để được ném. Bạn có thể sử dụng các ngoại lệ

std::invalid_argument

(cung cấp một giá trị có ý nghĩa với nó - "p is NULL"), nhưng bạn sẽ phải thực hiện kiểm tra chính mình.

+0

Cảm ơn, đây là câu trả lời tôi đang tìm kiếm. –

9

Thông thường, trong C++ (hoặc C cho vấn đề đó), bạn không bao giờ dereference con trỏ NULL. Thực hiện việc này có hành vi không xác định (có thể là sự phân đoạn về bất kỳ triển khai nào mà tôi biết, nhưng bất kỳ điều gì có thể xảy ra theo tiêu chuẩn). Nó có thể là một điều xấu trong các ngôn ngữ khác là tốt, nhưng tôi không biết những người đủ để khẳng định điều đó.

Tốt nhất là ngăn chặn tình huống hơn là cố gắng phục hồi từ nó (không thể thực hiện được trong C hoặc C++).

Các mô hình thông thường để ngăn chặn một số lỗi lập trình có liên quan là sử dụng assert() bên trong cơ thể chức năng như: các cuộc gọi

int foo(int* myint) 
{ 
    // Ensure myint is not NULL 
    assert(myint); 

    // Do something with myint 
    (*myint)++; 

    return *myint; 
} 

như vậy assert() được hoàn toàn phớt lờ trên phát hành xây dựng và do đó không có chi phí trong sản xuất. Họ chỉ giúp phát triển. Về gỡ lỗi xây dựng, và nếu điều kiện không được đáp ứng, chương trình hủy bỏ ngay lập tức với một thông báo lỗi rất rõ ràng. Chạy nó thông qua một trình gỡ lỗi, bạn có thể dễ dàng kiểm tra ngăn xếp cuộc gọi để điều tra vì lý do chính xác.

+5

Quan trọng trong C# vi Java nó cũng là thực hành xấu dựa vào việc bắt con trỏ null (chỉ ngoại lệ là phục hồi mức rất cao từ tất cả các ngoại lệ thời gian chạy, ví dụ trong một hồ bơi thread). Họ có nghĩa là để làm cho nó dễ dàng hơn để tìm lỗi lập trình. – Thirler

+0

Hãy nhớ rằng assert() sẽ đượC# ifdef'd out nếu mã xảy ra được biên dịch với NDEBUG được định nghĩa (-DNDEBUG). – daddesio

4

FTR, trong C# bạn không sử dụng NullReferenceException giây cho mọi thứ trừ khi bạn muốn bị các đồng đội của bạn đâm. Thay vào đó, có một ArgumentNullException để từ chối đối số null. NRE có nghĩa là được ném bởi thời gian chạy, không phải bạn. Tuy nhiên, lưu ý rằng không có lợi thế thực sự của điều này trong một xác nhận bởi vì bạn không nên bắt một trong những điều này: nếu chúng được ném ra, chúng chỉ ra một lỗi. Đây là những gì Eric Lippert gọi boneheaded exceptions và chúng là lỗi darn của riêng bạn, và không có mã nào của bạn nên làm đặc biệt với chúng.

2

Theo con trỏ null Dereferencing null sẽ dẫn đến hành vi không xác định, phần lớn kết thúc ứng dụng với lỗi phân đoạn. Trong Visual Studio, bạn có thể sử dụng các phần mở rộng như Xử lý ngoại lệ có cấu trúc (SEH), cho phép bắt giữ dereferencing con trỏ null.

2

Trong gần như tất cả các trường hợp liên quan đến việc sử dụng sai con trỏ rỗng (đặc biệt, hủy kết nối nó), C++ Standard chỉ đơn giản là rời khỏi hành vi không xác định. Không có loại ngoại lệ cụ thể nào được cung cấp cho (và sẽ không có ngoại lệ nào được ném). Tuy nhiên,

Tuy nhiên, một ngoại lệ có thể xảy ra đối với quy tắc này.std::function, mà là một C++ 11 mẫu tiêu chuẩn thư viện mà có thể được sử dụng để quấn chức năng, có thể được gán một con trỏ null:

std::function<void(int)> func = nullptr; 

Và nếu bạn sau đó thực hiện một nỗ lực để gọi hàm bọc bởi nó bằng cách làm func(arg); đối với một số đối số arg, nó sẽ ném một ngoại lệ std::bad_function_call.

Đây là, tất nhiên, không hoàn toàn tương đương với ngoại lệ con trỏ null của các ngôn ngữ khác, vì nó ít phổ biến hơn.

5

Không có ngoại lệ tiêu chuẩn trong C++ cho dereferencing con trỏ NULL.

Nếu bạn muốn, bạn có thể tự mình thực hiện. Trên UNIX thiết lập một bộ xử lý tín hiệu SIGSEGV và ném một ngoại lệ từ trình xử lý. Trên Windows, sử dụng API _set_se_translator() để cài đặt trình xử lý "Ngoại lệ có cấu trúc".

Các vấn đề liên quan