WSACleanup和atExit

时间:2009-06-09 08:25:25

标签: c++ winsock atexit wsastartup wsacleanup

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

3 个答案:

答案 0 :(得分:4)

如果您有一个多线程应用程序且某些线程仍然连接,则另一端的应用程序可能不喜欢连接终止的方式。所以最好在main()终止之前以有序的方式关闭所有通信,当你这样做时,你也可以调用WSACleanup。

答案 1 :(得分:2)

我同意RAII方法是有利的。

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

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

  1. 某处出口被调用或main()超出范围
  2. 调用过程中定义的atexit处理程序。
  3. 所有句柄都被销毁。
  4. 在dll中定义的atexit处理程序被调用。
  5. 如果在进程中的处理程序之前注册了dll中的atexit处理程序,则首先调用进程处理程序并在调用dll处理程序之前销毁句柄并不重要。当调用清理代码时,这导致win32异常,因为dll拥有的所有句柄都不再有效。

    此效果代码保存线程,互斥锁,文件,套接字等句柄。如果它们在dll中分配,则必须在调用exit之前清除它们,或者根本不清除它们。

    顺便说一句,我不是反窗口,如果我错了或任何人都知道任何解决方法,我很想知道,因为这会导致我在应用程序清理中产生无法解释的痛苦。在应用程序退出时获取win32异常后,我认为这是在c ++运行时调试退出处理。

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

答案 2 :(得分:1)

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