2012-07-07 27 views
7

Nhìn vào một số mã cũ chúng tôi có rất nhiều điều như sau:Một chuỗi có thể ném một ngoại lệ khi đọc một nguyên thủy?

// This is dumb 
string do_something(int in) 
{ 
    stringstream out; 
    try 
    { 
     out << std::fixed << in; 
    } 
    catch(std::exception &e) 
    { 
     out << e.what(); 
    } 

    return out.str(); 
} 

// Can't we just do this? Can this ever fail? 
string do_something_better(int in) 
{ 
    stringstream out; 
    out << std::fixed << in; 
    return out.str(); 
} 

Khi một stringstream đọc một nguyên thủy nó có thể bao giờ ném một ngoại lệ? Điều gì về khi đọc một chuỗi?

+11

Mã đó mất trí.Bạn đang gặp lỗi do luồng phát sinh và sau đó sử dụng ** luồng tương tự ** để cố gắng truyền đạt lỗi đó. Tệ hơn nữa, bạn đang xả rác mã cấp thấp của bạn với xử lý ngoại lệ hoàn toàn vô nghĩa mà không có gì để * khôi phục * từ lỗi, khiến luồng trong trạng thái bị hỏng. Bạn nên bắt các lỗi này ở mức mà bạn có thể * làm * một cái gì đó về chúng, ngay cả khi nó chỉ cảnh báo người dùng và hủy bỏ chương trình. Đây là một sự lạm dụng hoàn toàn về xử lý ngoại lệ. – meagar

+0

Nó có thể ném ngoại lệ, nhưng chỉ khi bạn đã kích hoạt chúng bằng cách gọi 'out.exceptions (selected_exceptions)'. Một luồng được xây dựng mặc định không ném ngoại lệ (ngoại trừ 'bad_alloc', mà bạn khó có thể xử lý ở đây). –

+0

Bạn hoàn toàn có thể xử lý 'bad_alloc'. Chỉ cần miễn phí một bó bộ nhớ. –

Trả lời

7

Tóm tắt một vài câu trả lời

Theo mặc định, luồng không ném ngoại lệ. Họ có thể nếu họ được kích hoạt.

stringstream out; 
out.exceptions(std::ios::failbit); // throw exception if failbit gets set 

Theo std Apache C++ Standard Library User's Guide

Cờ :: ios_base :: badbit chỉ ra vấn đề với bộ đệm dòng cơ bản. Những vấn đề này có thể là:

Thiếu bộ nhớ. Không có bộ nhớ có sẵn để tạo bộ đệm, hoặc bộ đệm có kích thước 0 vì các lý do khác (chẳng hạn như được cung cấp từ bên ngoài luồng) hoặc luồng không thể cấp phát bộ nhớ cho dữ liệu nội bộ của nó, như với std :: ios_base :: iword() và std :: ios_base :: pword().

Bộ đệm luồng cơ bản ném ngoại lệ. Bộ đệm luồng có thể mất tính toàn vẹn, như thiếu bộ nhớ, hoặc lỗi chuyển đổi mã hoặc lỗi đọc không thể khôi phục từ thiết bị bên ngoài. Bộ đệm luồng có thể biểu thị sự mất tính toàn vẹn này bằng cách ném một ngoại lệ, được phát hiện bởi luồng và kết quả trong việc thiết lập badbit trong trạng thái của luồng.

Nói chung, bạn nên nhớ rằng badbit cho biết tình trạng lỗi có khả năng không thể phục hồi, trong khi failbit cho biết tình huống có thể cho phép bạn thử lại thao tác không thành công.

Vì vậy, nó có vẻ như cách an toàn nhất để làm điều này sẽ

string do_something(int in) 
{ 
    stringstream out; // This could throw a bad_alloc 
    out << std::fixed << in; // This could set bad or fail bits 

    if(out.good()) 
    { 
     return out.str(); 
    } 
    else 
    { 
     return ""; 
    } 
} 

Đây là quá mức cần thiết mặc dù bởi vì theo Handling bad_alloc nếu tạo dòng thất bại, có những vấn đề lớn hơn để lo lắng về, và chương trình có lẽ sẽ thoát. Vì vậy, giả sử nó được quá khứ tạo ra các dòng, nó có thể nhưng rất không chắc chắn rằng các badbit được thiết lập. (Luồng được phân bổ với bộ nhớ < sizeof (int)).

Nó cũng không chắc chắn rằng các failbit được thiết lập (không chắc chắn của một trường hợp sử dụng để đọc ra khỏi ngăn xếp khác hơn là một ngăn xếp tham nhũng). Vì vậy, các mã sau đây là đủ, như phục hồi từ một lỗi dòng tại thời điểm này là unlikley.

string do_something(int in) 
{ 
    stringstream out; 
    out << std::fixed << in; 
    return out.str(); 
} 
2

Tất cả các luồng, bao gồm istringstreams, có thể ném ngoại lệ (có thể điều khiển bằng ios::exceptions) về đọc, ví dụ: khi hết dữ liệu đầu vào. Ngoài ra, chúng có thể ném khi hết bộ nhớ (ví dụ: khi xây dựng chuỗi hiện đang đọc).

Ví dụ mã của bạn, thực hiện viết (?) AFAIK viết và int không được tạo bất kỳ ngoại lệ nào, ngoài lỗi bộ nhớ rõ ràng (mã của bạn không xử lý tốt).

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