#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.
==
даст желаемый результат в любое время, когда код, необходимый для проверки одного и того же экземпляра строки. Я думаю, что «вы не можете» сформулировано слишком сильно.