我正在尝试为我的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,但是我想我会在这里发帖,看看是否有人对为什么在这种情况下会发生崩溃有什么见解。
2条答案
按热度按时间bnl4lu3b1#
我能想到的最好的猜测是
http_server
可能会启动额外的线程甚至分叉。这可能会导致io_context
和朋友在startLocalhost
返回后被访问。为了解释崩溃位置出现在指示的行,我可以添加一些启发式的东西,在ioc
的析构函数期间已经关闭了一些东西在这种情况下,您可以做一件简单的事情:拆分初始化并使用需要
error_code
的重载来代替使用它们。hfwmuf9z2#
在我的例子中,我尝试在MacOS M1处理器上的Ableton Live 11中运行的VST3音频插件中使用非Boost ASIO。在中使用VST3插件时,我遇到了同样的崩溃。在其他DAW应用程序(如Reaper)中使用相同的插件不会导致崩溃。在Windows上的Ableton Live 11中也不会发生崩溃。
我把范围缩小到以下几个问题:
在
asio/detail/impl/service_registry.hpp
中,下面的方法尝试返回一个函数指针地址到create/factory方法。具体来说,这一行:
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到插件中,没有链接。编辑
根据最新调查结果修改了最初的帖子,使其更加明确。