Как решить, где обрабатывать исключение - в рамках функции оно было выброшено или в глобальном? - PullRequest
0 голосов
/ 10 января 2009

Я пишу клиент-серверное приложение для Windows, используя WinSock, и у меня есть класс для сервера.
при инициализации сервера у меня такой код:


class Server {
    static const int MaxClients = 10;
    std::vector connections;
    CRITICAL_SECTION cs;
    int port;
    SOCKET ServerSocket;
    sockaddr_in ServerAddress;
    void init(); 
public:
    Server(int Port);
    void addConnection(const Client& newClient); 
    void closeConnection(int index); 
    void Listen();
    int size(); 
    /*virtual void ClientService();
    virtual void SendMsg(const std::string& msg);*/
    virtual ~Server();
};

void Server::init() {
    WSADATA wsaData;
    if(WSAStartup(MAKEWORD(2, 2), &wsaData))
        throw Exception("WinSock init failed");
    ServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (ServerSocket == INVALID_SOCKET)
        throw Exception("Socket failed to create!");
    ServerAddress.sin_family = AF_INET;
    ServerAddress.sin_addr.s_addr = htonl(INADDR_ANY); 
    ServerAddress.sin_port = htons(port);
    if(bind(ServerSocket,(sockaddr*)&ServerAddress,sizeof(ServerAddress)) == SOCKET_ERROR)
    {
        throw Exception("Binding failed");
        closesocket(ServerSocket); 
    }
}

где мне нужно обрабатывать исключения? Здесь, в init () закрытый метод (который вызывается из конструктора) или в основной функции? Какие-либо правила существуют, где разместить обработчики для исключений и от чего это зависит?

Ответы [ 3 ]

4 голосов
/ 10 января 2009

Основное правило заключается в том, что вы ловите исключения только в той части кода, где вы можете обработать это. Обрабатывая его, я имею в виду, что вы можете предпринять некоторые действия, основанные на выданном исключении, например, попытаться создать сокет в другой раз или попытаться использовать другую конфигурацию.

Кроме того, необходимо пересмотреть исключения, которые пересекают границы библиотеки. В зависимости от контекста вы можете захотеть перехватить их и повторно выдать исключение другого типа, например, чтобы скрыть детали реализации от клиента библиотеки.

3 голосов
/ 10 января 2009

Это зависит от того, собираетесь ли вы обработать исключение, например, Повторите попытку с немного другим вводом или решите проигнорировать проблему и продолжить в любом случае (редко подходит, но может быть полезным). В этом случае вы можете захотеть перехватить исключение, близкое к его источнику.

В большинстве случаев единственное, что вы действительно можете сделать с исключением, это зарегистрировать его и прервать операцию (например, предоставить пользователю страницу с ошибкой в ​​веб-приложении или вызвать дружественное сообщение «эта программа потерпела крах, извините») диалог и выход). В этом случае ваш блок catch, скорее всего, будет довольно близко к вершине стека - например, в основном методе.

0 голосов
/ 10 января 2009

Что касается вопроса о перехвате исключения в области действия функции, в которую оно было брошено (т. Е. В функции init()), то редко имеет смысл перехватывать исключение в области действия, в которую оно было брошено. По сути это будет означать, что вы обнаружили ошибку и знаете, как ее обработать (и собираетесь ее обрабатывать), но вы используете исключение, чтобы выполнить не что иное, как передачу управления другой части вашей функции. .

Хотя могут быть случаи, когда это может иметь смысл (хотя это может быть запах кода, указывающий на то, что функция достаточно сложна, чтобы ее можно было реорганизовать), логика обработки этой ошибки (поскольку она равна обрабатываются) должны использовать более распространенные методы потока управления, такие как if операторы или break. Даже крайне непопулярный goto может быть предпочтительнее, чем выбрасывать исключение, только если оно обрабатывается в той же функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...