c++ 在动态库中示例化boost::beast导致崩溃

ybzsozfc  于 2023-01-28  发布在  其他
关注(0)|答案(2)|浏览(259)

我正在尝试为我的C++应用程序实现一个非常简单的本地HTTP服务器-我在macOS上使用XCode。我必须从动态加载的库中实现它,而不是程序的“主”线程。我决定尝试使用boost::beast,因为应用程序的另一部分已经使用了boost库。我正在尝试实现this example,但在我的库的上下文中,而不是作为其主程序的一部分。
此库的主机应用程序调用以下函数以启动本地主机服务器,但在示例化“acceptor”时崩溃:

extern "C" BASICEXTERNALOBJECT_API long startLocalhost(TaggedData* argv, long argc, TaggedData * retval) {
        
        try {
           
               string status;
               retval->type = kTypeString;

               auto const address = net::ip::make_address("127.0.0.1");
               unsigned short port = static_cast<unsigned short>(std::atoi("1337"));

               net::io_context ioc{1};

               tcp::acceptor acceptor{ioc, {address, port}};  // <-- crashes on this line
               tcp::socket socket{ioc};
               http_server(acceptor, socket);

               ioc.run();
               
               status = "{'status':'ok', 'message':'localhost server started!'}";
               retval->data.string = getNewBuffer(status);
               
           }
           catch(std::exception const& e)
           {
               
               string status;
               
               //err_msg = "Error: " << e.what() << std::endl;
               
               status = "{'status':'fail', 'message':'Error starting web server'}";
               retval->data.string = getNewBuffer(status);
               
           }

     return kESErrOK;
        
}

在单步执行代码时,我看到XCode在执行包含tcp::acceptor ...的行时报告了一个错误:
Thread 1: EXC_BAD_ACCESS (code=1, address=0x783c0a3e3f22650c)
并且在scheduler.h中的函数的单行代码中突出显示:

//Get the concurrency hint that was used to initialize the scheduler.

int concurrency_hint() const
{
   return concurrency_hint_; //XCode halts here
}

我在争论是否应该包括一个不同的C++ Web服务器,比如Drogon,而不是boost::beast,但是我想我会在这里发帖,看看是否有人对为什么在这种情况下会发生崩溃有什么见解。

bnl4lu3b

bnl4lu3b1#

我能想到的最好的猜测是

  • 也许你的http_server可能会启动额外的线程甚至分叉。这可能会导致io_context和朋友在startLocalhost返回后被访问。为了解释崩溃位置出现在指示的行,我可以添加一些启发式的东西,在ioc的析构函数期间已经关闭了一些东西
  • 我的另一个想法是,实际上接受器的打开/绑定会抛出异常,但由于共享模块和主程序中类型可能不兼容,抛出的异常实际上不会被捕获,并导致异常终止。2如果主程序也使用Boost库,但使用它们的不同副本(构建/版本),这可能会更容易发生。

在这种情况下,您可以做一件简单的事情:拆分初始化并使用需要error_code的重载来代替使用它们。

hfwmuf9z

hfwmuf9z2#

在我的例子中,我尝试在MacOS M1处理器上的Ableton Live 11中运行的VST3音频插件中使用非Boost ASIO。在中使用VST3插件时,我遇到了同样的崩溃。在其他DAW应用程序(如Reaper)中使用相同的插件不会导致崩溃。在Windows上的Ableton Live 11中也不会发生崩溃。
我把范围缩小到以下几个问题:
asio/detail/impl/service_registry.hpp中,下面的方法尝试返回一个函数指针地址到create/factory方法。

template <typename Service>
Service& service_registry::use_service(io_context& owner)
{
  execution_context::service::key key;
  init_key<Service>(key, 0);
  factory_type factory = &service_registry::create<Service, io_context>;
  return *static_cast<Service*>(do_use_service(key, factory, &owner));
}

具体来说,这一行:factory_type factory = &service_registry::create<Service, io_context>;
当在Xcode中调试时,在工作的主机中,当检查factory时,它显示链接到service_registry::create<Service, io_context>静态方法的正确地址。
然而,在Ableton Live 11中,它不指向任何东西--不知何故,静态方法的地址无法正确解析。这导致了一系列问题,最终导致试图在service_registry::do_use_service方法中调用asio/asio/detail/impl/service_registry.ipp中的factory函数指针。由于它不指向正确的create方法,因此没有创建任何东西,这导致了未初始化的对象。包括调度器示例。
因此,在kqueue_reactor.ipp中调用scheduler_.concurrency_hint()时,计划程序未初始化,并导致EXC_BAD_ACCESS错误。
我不清楚为什么在某些主机进程下,动态加载插件不能解析静态方法地址,而在其他进程下则没有问题。在我的例子中,我直接将asio.hpp编译为独立ASIO到插件中,没有链接。

编辑

根据最新调查结果修改了最初的帖子,使其更加明确。

相关问题