Повысьте Asio, если условие оценивается по-разному в компиляциях со статической библиотекой и библиотекой dll, что приводит к исключению в клиентской библиотеке cpp ввода-вывода сокета

#c #visual-studio #socket.io #boost-asio #critical-section

#c #visual-studio #socket.io #boost-asio #критический раздел

Вопрос:

В зависимости от того, как скомпилирована библиотека socketio c (статическая библиотека или dll) для следующего простого тестового кода, результатом будет либо рабочий исполняемый файл, либо тот, который выдает исключение.

Однако, если создание экземпляра io_service закомментировано, например.:

// boost::asio::io_service io_service;

тогда версия на основе статической библиотеки также работает без исключений. Похоже, что существует некоторое взаимодействие между io_service, созданным в main(), с io_service, расположенным в библиотеке SocketIO.

 #define BOOST_ALL_NO_LIB

#include "../socketio/src/sio_client.h"
#include <boostasioio_service.hpp>
#include <memory>
#include <fstream>
#include <string>
#include <boost/lexical_cast.hpp>


int main(int argc, char* argv[]) {
    boost::asio::io_service io_service;
    //auto io_service_work = std::make_shared<boost::asio::io_service::work>(io_service);
    sio::client client_;
    client_.connect("http://localhost:1337");
    //io_service.run();
}
  

Хотя полный исходный код тот же (не считая необязательных различий в условной компиляции), оценка следующей строки приводит к TRUE в статической библиотеке и FALSE в версии Dll:

if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, op))

Проверьте полный код из win_iocp_io_service.ipp

 void win_iocp_io_service::post_deferred_completion(win_iocp_operation* op)
{
  // Flag the operation as ready.
  op->ready_ = 1;

  // Enqueue the operation on the I/O completion port.
  if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, op)) // DIFFERENT RESULT IN STATIC-LIB AND DLL
  {
    // Out of resources. Put on completed queue instead.
    mutex::scoped_lock lock(dispatch_mutex_);
    completed_ops_.push(op);
    ::InterlockedExchange(amp;dispatch_required_, 1);
  }
}
  

Пожалуйста, найдите тестовый пакет с двумя почти идентичными решениями VS2015. Оба решения содержат 2 проекта (siotest и socketio). Пакет должен быть автономным, поэтому для компиляции и тестирования не требуется дополнительных библиотек (таким образом, несколько больший размер zip-файла).

Zip-файл, содержащий тестовый пакет

Socketio — это библиотека, включающая сокет c 11 с открытым исходным кодом.реализация клиента ввода-вывода из

Клиентская реализация ввода-вывода сокета C 11

Siotest — это простая тестовая программа, которая подключается к серверу SocketIO.

И Socketio, и Siotest используют boost asio ioservice, хотя созданная переменная io_service в Siotest не используется после создания экземпляра.

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

Программный пакет, содержащий статические версии lib и dll

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

Другая версия решения в папке siotest lib почти полностью идентична, но связывание проекта socketio является статической библиотекой, в отличие от динамической связанной библиотеки в siotest dll.

Результат ошибочного запуска socketio_lib показан на скриншоте ниже Исключение

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

Очевидно, что между двумя версиями программного обеспечения есть некоторая разница, хотя исходный код точно такой же. Пример представляет собой упрощение нашей программной среды, в которой мы хотели бы использовать как клиентскую библиотеку C для ввода-вывода сокетов, так и службу ввода-вывода Boost Asio.

Мы хотели бы понять источник проблемы и иметь возможность скомпилировать наш код как статическую библиотеку. Любые советы приветствуются.

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

1. Не пытайтесь рассуждать о неопределенном поведении. Это ни к чему не приводит. Связывание несовместимых версий библиотек нарушает правила ODR. Не делайте этого. Исправьте совместимость флагов компилятора / компоновщика

2. Какие библиотеки в этом случае, по вашему мнению, несовместимы?

3. Давайте не будем говорить о мнениях. Для надежного взаимодействия с библиотеками C требуется соответствующий ABI. На практике способ добиться этого — точно сопоставить версию компилятора и флаги (архитектура, исключения и т. Д.) С теми, С которыми была создана библиотека, которую вы хотите связать. Неудивительно, что это причина, по которой библиотеки с открытым исходным кодом сияют (потому что вы можете создать библиотеку самостоятельно), а также почему дистрибутивы Linux имеют «благословенный» набор инструментов и опций, который используется для всего их репозитория пакетов и обновляется только по всем направлениям.

4. Лучшие результаты при поиске в Google «abi odr совместимый двоичный c » очень полезны, если вам нужно больше информации.

5. Похоже, что использование asio без повышения просто устраняет нарушение ODR.