2013-01-11 15 views
6

Tôi kiểm tra mã C++ của mình bằng googletest. Khi một ngoại lệ được ném vector::_M_range_check vì một std::vector được truy cập với một chỉ số sai, báo cáo googletest:Google Test và std :: ngoại lệ dải vector

C++ exception with description "vector::_M_range_check" thrown in the test body. 

Tuyệt vời, bây giờ tôi cũng muốn biết đó vector, trong đó chỉ số và đó phạm vi. Làm thế nào tôi có thể dễ dàng có được thông tin này, giữ mã thử nghiệm trong các trường hợp thử nghiệm đơn vị googletest?

(tôi gần như bắt đầu từ lâu cho Java với tốt cũ IndexOutOfBoundsException của nó ...)

+0

--gtest_catch_exceptions = 0 – JaredC

+0

@JaredC lá cờ này chấm dứt kiểm tra sau khi ngoại lệ được ném, nhưng đầu ra không cung cấp thêm thông tin về nguồn gốc của ngoại lệ (vectơ, chỉ mục, phạm vi) – clstaudt

+2

@cls: Nếu bạn chạy kiểm tra trong một trình gỡ lỗi, hoặc kiểm tra kết xuất lõi sau khi kết thúc, sau đó bạn sẽ thấy nơi mà các ngoại lệ unhandled đã được ném từ. Ngoài ra, bạn có thể đặt một điểm ngắt trên 'std :: __ throw_out_of_range', đó là hàm mà thư viện GNU gọi để ném ngoại lệ. –

Trả lời

8

Nếu bạn chạy với tùy chọn dòng lệnh này sau đó ngoại trừ của bạn sẽ bong bóng tất cả các lối thoát:

--gtest_catch_exceptions=0 

Thực hiện việc này bên trong trình gỡ lỗi sẽ cung cấp cho bạn chính xác stacktrace của ngoại lệ.

+0

Phải, nhưng không phải chỉ mục và giới hạn là nguyên nhân của lỗi. – clstaudt

+3

@cls Thông tin đó sẵn có khi trình gỡ lỗi đã dừng. – JaredC

6

Google thử nghiệm không liên quan ở đây. Việc thực thi Thư viện chuẩn C++ của bạn là ném một ngoại lệ, và tùy thuộc vào việc thực hiện Thư viện chuẩn C++ của bạn để quyết định cách tiết ra các ngoại lệ của nó.

Vì bạn đang nhận được ngoại lệ, tôi cho rằng bạn đang sử dụng std::vector::at thay vì std::vector::operator[]. Có một số phương pháp có thể bạn có thể thực hiện để nhận thêm thông tin.

Đầu tiên, bạn có thể thay thế các cuộc gọi đến at bằng các cuộc gọi đến operator[] (cá nhân, tôi không tìm thấy phạm vi kiểm tra ngoại lệ là rất hữu ích và có phí hoạt động) và sử dụng tiêu chuẩn C++ của bạn Gỡ lỗi trình lặp của thực hiện thư viện. Ví dụ, với g ++, nếu tôi sử dụng operator[] và biên dịch với -D_GLIBCXX_DEBUG bật phạm vi kiểm tra operator[], tôi nhận được một lỗi tương tự như sau:

/usr/include/c++/4.3/debug/vector:237:error: attempt to subscript container 
    with out-of-bounds index 0, but container only holds 0 elements. 

Thứ hai, bạn có thể thay thế các cuộc gọi đến at với các cuộc gọi đến test_at hoặc tương đương: (chưa được kiểm tra)

template <typename T> 
T& test_at(std::vector<T>& v, size_t n) { 
    // Use Google Test to display details on out of bounds. 
    // We can stream additional information here if we like. 
    EXPECT_LT(n, v.size()) << "for vector at address " << &v; 

    // Fall back to at, and let it throw its exception, so that our 
    // test will terminate as expected. 
    return v.at(n); 
} 
0

vector::at(size_type n) được ghi nhận là ném out_of_range trên không hợp lệ n (23.2.3p17). out_of_range không mang thông tin trên thùng sơn hoặc chỉ số, vì vậy bạn sẽ phải quấn at nếu bạn muốn có thông tin rằng:

template<typename T> struct my_vector: public std::vector<T> { 
    using std::vector<T>; 
    struct at_out_of_range: public std::out_of_range { 
    my_vector *vector; 
    size_type size; 
    size_type n; 
    at_out_of_range(my_vector *vector, size_type size, size_type n): 
     std::out_of_range("at_out_of_range"), vector(vector), size(size), n(n) {} 
    }; 
    reference at(size_type n) { 
    try { 
     return std::vector<T>::at(n); 
    } catch(std::out_of_range &ex) { 
     std::throw_with_nested(at_out_of_range(this, size(), n)); 
    } 
    } 
}; 

Lưu ý rằng at không phải là ảo, vì vậy bạn phải gọi thông qua các gói at để có được Ngoại lệ lồng nhau.