2010-07-23 23 views
21

Tôi đã tham gia một cái nhìn tại the assert() reference page và tôi đã bị mắc kẹt trong khi tôi đọc những ví dụ đưa ra:Tôi có sử dụng sự hiểu lầm() không?

/* assert example */ 
#include <stdio.h> 
#include <assert.h> 

int main() 
{ 
    FILE * datafile; 
    datafile=fopen ("file.dat","r"); 
    assert (datafile); 

    fclose (datafile); 

    return 0; 
} 

Trong ví dụ này, khẳng định được sử dụng để hủy bỏ việc thực hiện chương trình nếu datafile so sánh bằng 0, trong đó xảy ra khi cuộc gọi trước đến fopen không thành công.

Tôi hoàn toàn đồng ý rằng nếu fopen() không thành công, assert() sẽ hủy bỏ việc thực thi. Tuy nhiên tôi lo ngại về tính đúng đắn của ví dụ này:

Theo tôi assert() là có để phát hiện các trường hợp mà bình thường không thể xảy ra (như đi qua một con trỏ NULL đến một hàm mà tài liệu khẳng định nó bị cấm).

Trong ví dụ này, việc không mở tệp không phải là điều mà thường không thể xảy ra. Trong thực tế, tôi có thể thấy hàng chục lý do tại sao điều này sẽ thất bại. Tệp không thể tồn tại, chương trình có thể chạy mà không có đặc quyền bắt buộc, v.v.

Tôi thà làm một cái gì đó như:

/* not longer an assert example */ 
#include <stdio.h> 
#include <assert.h> 

int main() 
{ 
    FILE * datafile; 
    datafile=fopen ("file.dat","r"); 

    if (datafile != NULL) 
    { 
    // Do something, whatever. 
    fclose (datafile); 
    } else 
    { 
    // Report the error somehow. 
    } 

    return 0; 
} 

là hiểu biết của tôi về cách assert() nên được sử dụng không chính xác?


CHỈNH SỬA VÀ TIN TỨC TỐT!

Có vẻ như trang web được giới thiệu được cai trị bởi những người nghiêm khắc. Đây là thư tôi nhận được từ một trong những người bảo trì trang web:

Xin chào Julien, tôi phải đồng ý, mã ví dụ không được chọn. Nó có hiện đã được viết lại thành một cái gì đó phù hợp hơn.

Rất cám ơn vì đã chỉ ra điều này và xin lỗi về bất kỳ sự bất tiện nào mà điều này có thể gây ra cho bạn.

Trân trọng,

Và ví dụ Cập nhật:

/* assert example */ 
#include <stdio.h> 
#include <assert.h> 

void print_number(int* myInt) { 
    assert (myInt!=NULL); 
    printf ("%d\n",*myInt); 
} 

int main() 
{ 
    int a=10; 
    int * b = NULL; 
    int * c = NULL; 

    b=&a; 

    print_number (b); 
    print_number (c); 

    return 0; 
} 

Vui mừng khi thấy rằng một số người làm công việc của họ tốt trên Internet! ;)

+8

+1 Để nhận ra rằng đây là một ví dụ không tốt. +2 Để gửi thư cho các địa chỉ liên lạc trang web. –

+4

Sự hiểu biết của bạn là điểm trên. 'assert' là lỗi lập trình, không phải lỗi người dùng. – GManNickG

+0

Tôi đã xóa thẻ C++, vì không có mẩu tin C++ trong bài đăng. – Puppy

Trả lời

13

Bạn hoàn toàn đúng. Đây là cách sử dụng kém của assert.

+0

thực sự, khẳng định chỉ nên là phương sách cuối cùng được gọi là sự sụp đổ của thế giới – RvdK

+2

Cảm ơn phản hồi. Tôi đã viết cho trang liên hệ để thông báo cho họ về sự cố. Tôi tự hỏi nếu họ sẽ cập nhật nó. – ereOn

+0

+1 cho điều này có thể là câu trả lời tiềm năng ;-) – KedarX

1

thông báo nhỏ: nó sẽ tốt hơn nếu bạn viết ..

FILE * datafile = NULL; 

Ngoài ra, khẳng định chỉ hoạt động trong chế độ gỡ lỗi ... vì vậy phương pháp của bạn là tốt hơn.

+0

Vâng, đây không phải là mã của tôi. Và trong khi tôi thường khởi tạo các biến cục bộ, tại đây 'datafile' được gán ngay sau khi khai báo, vì vậy nó không quan trọng;) Điểm tốt về chế độ gỡ lỗi, tôi thậm chí còn không nghĩ về điều đó. – ereOn

+0

Điều gì khiến bạn nói rằng nó chỉ hoạt động ở chế độ gỡ lỗi? –

+1

@Praveen: khẳng định là macro chỉ thực hiện khi 'NDEBUG' không được xác định. Vì vậy, thường trong chế độ gỡ lỗi. – ereOn

2

Bạn thực sự đúng.Như những người khác đã chỉ ra, assert() sẽ có nhiều khả năng được biên soạn trong bản phát hành bản phát hành (Tôi đã thấy mọi người buộc các xác nhận được để lại trong bản phát hành bản phát hành).

Tôi chỉ muốn thêm một câu chuyện kinh dị liên quan đến câu hỏi này mà tôi đã nhìn thấy trên một mã-base:

assert(do_something() == NO_ERR); 

Một số người không nên được phép sử dụng một bàn phím.

+1

Đúng. Mặc dù nó phụ thuộc vào những gì do_something() làm. nếu do_something() thực sự là do_complex_validation_that_system_state_is_valid() thì nó * có thể * hợp lý nếu nó không có tác dụng phụ – jcoder

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