Сравнить boost::system::error_category
Следующее сравнение не выполняется для ошибки, которая выводит "asio.misc" для errorCode.category(). Name() и "конец файла" для errorCode.message()
Если он утверждает, что находится в категории asio.misc, то почему условие if (errorCode.category() == boost::asio::error::misc_category) оценивается как ложное?
Поиск в Google (включая ответы здесь) говорит, что boost::system::error_code может иметь одинаковое значение в более чем одной категории, поэтому я предполагаю, что для получения правильного сообщения и значения мы должны сравнить boost::system::error_category а также boost::system::error_code::value.
Как правильно сравнить категорию, если она не работает?
Код в вопросе:
//--------------------------------------------------------------------------------------------------
std::string ClientSocketASIO::ErrorCodeToString(const boost::system::error_code & errorCode)
{
std::ostringstream debugMsg;
debugMsg << " Error Category: " << errorCode.category().name() << ". "
<< " Error Message: " << errorCode.message() << ". ";
if( errorCode.category() == boost::asio::error::misc_category )
{
switch (errorCode.value())
{
case boost::asio::error::eof:
debugMsg << ". Server has disconnected.";
break;
case boost::asio::error::connection_refused:
debugMsg << ". Connection Refused";
break;
default:
debugMsg << ". Unknown Error.";
break;
}
}
else
{
debugMsg << ". Unknown Error category.";
}
return debugMsg.str();
}
РЕДАКТИРОВАТЬ:
Согласно https://theboostcpplibraries.com/boost.system и Boost::file_system: Проверка кодов ошибок
Люди обычно и по ошибке пишут код, сравнивая только значение ошибки, а не категорию. Одно только значение ошибки не является уникальным и может встречаться в нескольких категориях. Пользователи также могут создавать свои собственные коды ошибок и категории. Следовательно, оба должны быть сопоставлены. Это, я полагаю, не влияет на большое количество приложений, потому что они в любом случае используют только одну функцию или библиотеку для ускорения своего проекта, и / или большинство кодов ошибок отображаются на коды ошибок Windows, которые сделали все возможное, чтобы не сталкиваются.
Мне пришлось сесть на другой компьютер, чтобы просмотреть список рассылки буста, так как моя работа блокирует практически все.
http://boost.2283326.n4.nabble.com/Compare-boost-system-error-category-td4692861.html
Согласно парню из-за этого сравнение не удается, потому что библиотека boost статически связана, а boost::system::error_category::operator == сравнивает адреса, поэтому LHS - это адрес в одной библиотеке, а RHS это адрес в другом. Они не будут равны, когда они ожидаются.
Использование адреса для оператора == кажется мне очень глупым шагом. Я буду продолжать разглагольствовать об этом в списке рассылки поддержки и редактировать здесь для других, если будут обнаружены какие-либо новые знания.
На данный момент я динамически связываю и использую форму
//--------------------------------------------------------------------------------------------------
std::string ClientSocketASIO::ErrorCodeToString(const boost::system::error_code & errorCode)
{
std::ostringstream debugMsg;
debugMsg << " Error Category: " << errorCode.category().name() << ". "
<< " Error Message: " << errorCode.message() << ". ";
// IMPORTANT - These comparisons only work if you dynamically link boost libraries
// Because boost chose to implement boost::system::error_category::operator == by comparing addresses
// The addresses are different in one library and the other when statically linking.
//
// We use make_error_code macro to make the correct category as well as error code value.
// Error code value is not unique and can be duplicated in more than one category.
if (errorCode == make_error_code(boost::asio::error::connection_refused))
{
debugMsg << ". Connection Refused";
}
else if (errorCode == make_error_code(boost::asio::error::eof))
{
debugMsg << ". Server has disconnected.";
}
else
{
debugMsg << ". boost::system::error_code has not been mapped to a meaningful message.";
}
return debugMsg.str();
}
однако, это не работает, когда я статически соединяюсь, чтобы повысить также. Если у кого-то есть еще какие-либо предложения о том, как нам правильно сравнить boost::system::error_code и получить ожидаемые результаты, давайте перейдем к сути.
1 ответ
Стандарт C++ 11 подразумевает, что каждый экземпляр категории ошибок должен иметь глобально уникальный адрес, и сравнения равенства должны использовать этот адрес для сравнения. К сожалению, это не надежно в переносимом коде, только Dinkumware STL реализует истинную уникальность адресов в любом месте процесса и добавляет полный барьер памяти для достижения этого, то есть это дорого.
Качество реализации Boost такое же, как и у libstdC++ или libC++, при определенных обстоятельствах вы можете получить несколько экземпляров, которые могут иметь разные адреса.
В моем собственном коде я сначала выполняю оператор сравнения, а если это не удается, я выполняю strcmp() с именем категории (). На сегодняшний день это меня не укусило. Я лично считаю этот аспект категорий ошибок дефектом в стандарте, так как он требует реализации без заголовка, если вы хотите, чтобы она соответствовала, и даже если это не распространяется на RTLD_LOCAL, что означает, что вам нужно отступить на именованную общую память или какой-нибудь хак.