【问题标题】:Boost ASIO Access Violation on destruction of io_service在销毁 io_service 时提高 ASIO 访问违规
【发布时间】:2019-08-20 16:36:45
【问题描述】:

我目前正在从事一个项目,我在该项目中创建了一个 boost::asio::ip::udp::socket 并将其设置为异步侦听来自客户端的数据。我正在使用 CMake 为 Linux 和 Windows 10 部署环境生成我的项目文件。

我对使用 GCC 和 Clang 在 Linux 上运行的代码没有任何问题,但是,当我使用 MSVC 和 Visual Studio 在Release 模式下运行时,我会在程序退出时遇到访问冲突。

这是我得到的错误:

Exception thrown at 0x00007FFB51954989 (ntdll.dll) in Weave_Server.exe: 0xC0000005: Access violation writing location 0x0000000000000024.

堆栈显示此异常发生在我的 NetworkManager 类的销毁时:

编辑:这是具有我的 udp::socketio_service 对象的对象的 destrcutor。完整的析构函数被调用,错误来自io_service被销毁或udp::socket被清理的某个地方。 udp::socket 是一个 std::shared_ptr,当这个函数超出范围时将被销毁:

通过一些研究,我知道ntdll.dll 用于调试 Visual Studio C++ 项目的符号,这在发布模式下会崩溃是有道理的(因为不应加载调试符号)。

为什么项目会尝试从发布模式项目中访问任何调试符号?这是我需要在 CMake 文件中设置的设置吗?

这是我为该项目在CMakeLists.txt 中获得提升的地方:


if ( MSVC )
    set( Boost_USE_STATIC_LIBS          ON  ) 
else()
    set( Boost_USE_STATIC_LIBS          OFF  )
endif()
set( Boost_DETAILED_FAILURE_MSG     ON  )    # Useful error messages from boost
set( Boost_USE_STATIC_RUNTIME       OFF )    
set( Boost_DEBUG                    OFF )    # Print debug info from find boost

FIND_PACKAGE( Boost COMPONENTS system regex REQUIRED )

if( Boost_FOUND )
    message( STATUS      "Success, Boost found!" )
else()
    message( ERROR      "Cannot find boost! Exiting..." )
    return()
endif()

如果 Boost 是静态链接还是动态链接,我能想到的另一件事是更改,但我更改了 BOOST_USE_STATIC_LIBS 并且在两种设置中都会出现相同的错误。

有没有人知道为什么会抛出这个异常,或者我缺少一些设置来检查调试与发布?谢谢

【问题讨论】:

  • 从图片中我会查看析构函数第 23 行,看看你是否能说出它为什么会导致空指针取消引用。
  • 确保使用发布二进制文件进行发布配置,并使用调试二进制文件进行调试配置。在 Visual Studio 中,重要的是不要将这些用于基于 c++ 的代码。
  • 当我编译 boost 并将我的工具集指定为 msvc 时,使用 -gd 生成的库用于调试或不用于发布。在Visual Studio 项目中我不需要添加任何Additional Dependencies,只需添加一个Additional Library Directory 文件夹即可。 MSVC 是否有可能尝试链接到调试 lib 文件?
  • 它可能使用编译指示自动链接。
  • 我以前见过pragma链接语法用于其他事情,但我没有使用它来链接Boost(除非它在某处自动执行)。项目解决方案中是否有我可以查看链接器是否正在使用它的地方?

标签: c++ sockets visual-c++ boost boost-asio


【解决方案1】:

之所以出现这个问题,是因为当我的 NetworkManager 析构函数超出范围时,io_service 对象正在被销毁。这是有问题的,因为我使用的是udp::socket::async_recvFrom,它仍在尝试访问io_service 对象。

可以通过传入对io_service 对象的引用并通过默认构造函数创建套接字来解决该问题,或者,您可以使用指向io_service 的共享指针并传入该引用(如果不这样做)不想立即创建套接字。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-02
    • 2012-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多