6

可以通过 atExit 函数注册 WSACleanup 吗?我们有几个应用程序可以在代码中的不同点终止,因此我们希望避免将 WSACleanup 放在代码中的任何地方。目前我们通过 DllMain 调用 WSAStartup / WSACleanup,因为我们有一个所有这些应用程序都使用的 dll。但是,Microsoft 严格建议不要通过 DllMain 使用 WSAStartup / WSACleanup,因为这会导致死锁。我们可以将 WSAStarup 移出 DllMain,并在所有应用程序访问 Windows 套接字库之前在代码中的某一点调用它。而且,一旦我们调用 WSAStartup,我们就想使用 atExit 函数来注册对 WSACleanup 的调用。有没有人有这种方法的经验?谢谢!

4

3 回答 3

4

如果您有一个多线程应用程序并且某些线程仍然连接,那么另一端的应用程序可能不喜欢连接终止的方式。因此,最好在 main() 终止之前以有序的方式关闭所有通信,当您完成此操作后,您也可以调用 WSACleanup。

于 2009-06-09T09:10:11.457 回答
2

我同意 RAII 方法是有利的。

然而,一个警告:atExit 与 dll 和句柄混合在 Windows 上被破坏了。不幸的是,这也会影响 RAII,因为这是由 c++ 运行时使用 atExit 处理程序实现的。

在 Windows 上调用 atexit 处理程序的顺序:

  1. 某处 exit 被调用或 main() 超出范围
  2. 调用进程中定义的 atexit 处理程序。
  3. 所有的句柄都被破坏了。
  4. 调用 dll 中定义的 atexit 处理程序。

如果 dll 中的 atexit 处理程序在进程中的处理程序之前注册并不重要,首先调用进程处理程序并在调用 dll 处理程序之前销毁句柄。这会导致 win32 异常,当调用清理代码时,因为 dll 拥有的所有句柄都不再有效。

这会影响保存线程、互斥体、文件、套接字等句柄的代码。如果它们是在 dll 中分配的,则必须在调用 exit 之前清理它们或根本不清理它们。

顺便说一句,我不是反窗口,如果我错了,或者有人知道任何解决方法,我很想知道,因为这给我在应用程序清理带来了难以言喻的痛苦。在应用程序退出时获得 win32 异常后,我发现这是在 c++ 运行时调试退出处理。

我必须删除所有调用才能从我的代码中退出。我现在确保 dll 中没有静态数据控制句柄。所有静态句柄都由在 main 超出范围时被破坏的对象控制。

于 2009-06-10T14:09:06.037 回答
1

好吧,我认为不应使用 atExit 。您应该遵循将套接字库的初始化和销毁​​包装在一个类中的 RAII 原则。

于 2009-06-09T10:23:36.910 回答