Исключение C , чтобы ввести const char* и перехватить

#c #exception

#c #исключение

Вопрос:

Я пишу код, используя очень простое исключение на C .

но это работает не так, как я ожидаю.

и я не знаю, почему, хотя и в режиме отладки.

я прикрепляю картинку, которая показывает переменную в режиме отладки eclipse в точке перехвата.

я исключил, что поток кода перейдет в if оператор, но он перейдет в else оператор.

поскольку эта проблема слишком проста, я думаю, что я неправильно понял при обработке исключения, пожалуйста, исправьте мое понимание.

 throw "connection fail";
 

.

 catch(const char* e){
    if(e == "connection fail"){
        clients.erase(client);
        continue;
    }else{
        std::cout << e << std::endl;
        assert(NULL);
    }
}
 

введите описание изображения здесь

Комментарии:

1. == сравнивает указатели, а не значение строки см., возможно, другие вопросы не выбрасывайте const char* используйте некоторый подкласс std::exception

2. Подсказка: как вы сравниваете буферы символов, когда заданы два указателя, которые указывают на начало каждого буфера?

3. Подсказка: выбросить что-то производное от std::exception , если вы не хотите раздражать всех.

Ответ №1:

Вам повезло, что код работал не так, как ожидалось, есть большая вероятность, что так оно и было, а затем сломался, когда вы перестроили свой код через много лет.

 if(e == "connection fail"){
 

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

Чтобы на самом деле сравнить строки, либо используйте strcmp , либо преобразуйте один из операндов в std::string .

 try {
    throw "connection fail";

} catch( char const *e ) {
    if(std::string(e) == "connection fail") {
        std::cerr << "caught: " << e << std::endl;
    }
}
 

Лучшее решение — вместо этого создавать типы, производные от std::exception . Я бы изменил ваш код на:

 try {
    throw std::runtime_error("connection fail");

} catch( std::exception constamp; e ) {
    std::cerr << "caught: " << e.what() << std::endl;
}
 

Комментарии:

1. 1 за std::runtime_error совет. даже если нет рекомендаций о том, как выполнить очистку.

2. @Cheersandhth. -Если нет кода, указывающего, что делает OP client или clients что могло вызвать это исключение. Я мог бы продолжить о RAII и тому подобном, но для этого нужно придумать свой собственный пример потенциального варианта использования. Если вы хотите написать ответ, который показывает все это, вы получите мой голос.

Ответ №2:

Пожалуйста, не бросайте const char* , это не имеет смысла!

throw std::runtime_error("My Error");

catch (const std::runtime_erroramp; e)

или создайте свое собственное исключение, содержащее переменные, которые указывают на детали исключения, или различные типы объектов, которые указывают на проблему! Тогда вам не нужно выполнять какое-либо сравнение строк.

Ответ №3:

Вы не можете сравнивать строки в стиле C с == , вы должны использовать strcmp . Большую часть времени.

Это == только сравнение адресов указателей. В этом случае у вас есть две строки, поэтому они находятся по разным адресам, даже если они могут содержать одни и те же символы в строке.

Вы можете заставить == сравнение работать, если сможете убедиться, что обе строки на самом деле находятся в одном и том же месте в памяти. Вот способ заставить это работать:

 static const char * connection_fail = "connection fail";
throw connection_fail;

catch(const char* e){
    if(e == connection_fail){
        // ...
 

Лучшим решением было бы не бросать строки, а вместо этого бросать объекты, производные от std::exception . Они содержат what() метод, который можно использовать для получения строки, описывающей ошибку.

Комментарии:

1. «не могу» и «должен» — это слишком сильно сказано. однако в этом конкретном контексте совет не является необоснованным. тем не менее, имхо, было бы намного лучше решить реальную проблему, а именно, как повторить попытку или потерпеть неудачу.

2. @Cheersandhth. -Alf Я не думаю, что это слишком сильно — я не думаю, что я когда- либо видел случай, когда == это дало бы желаемый результат.

3. @MarkRansom, конечно, некоторые (или, я думаю, большинство) компиляторы будут правильно обрабатывать const char *str = "something"; ... if (str == "something") . Последнее, вероятно, было бы в функции, чтобы оно имело какой-либо смысл, но я решил, что интернирование строк достаточно распространено. Однако у меня нет доказательств, так что я могу ошибаться.

4. @MarkRansom: по-видимому, в этом случае выбрасывание и перехват происходят в одной и той же области, откуда именованный указатель можно очень эффективно сравнивать с самим собой. что касается «обязательного» использования strcmp , это может иметь довольно высокие накладные расходы по сравнению, например memcmp , с (я понятия не имею, почему). таким образом, и «не могу», и «должен» слишком сильны.

5. == даст желаемый результат в любое время, когда код, необходимый для проверки одного и того же экземпляра строки. Я думаю, что «вы не можете» сформулировано слишком сильно.