アプリ版:「スタンプのみでお礼する」機能のリリースについて

はじめまして。
現在、C++ Builder ver6.0 にて、ソケット通信のプログラムを作成しているのですが、受信処理を一定回数行うとwinsockのリソースを解放するWSACleanupが失敗してしまいます。1ファイル受信するごとに下記のソケットの初期化処理を入れています。
bool __fastcall CUdpSock::Init(void)
{
  WORD wVersionRequested; // socket version
  int errorStatus;
  WSADATA wsaData;

  /* WinSockの初期化を行う */
  wVersionRequested = MAKEWORD(1, 1); // バージョン 1.1 を要求する
  nErrorStatus = WSAStartup(wVersionRequested, &wsaData);
  if ( nErrorStatus != 0 )
  {
    m_msg.printf("WinSockの初期化失敗\n");
    Application->MessageBox(m_msg.c_str(), "ソケットの初期化", MB_ICONINFORMATION | MB_OK);
    return false;
  }
  if (atexit((void (*)(void))(WSACleanup))) // 終了時にWinSockのリソースを解放するようにしておく
  {
    m_msg.printf("atexit(WSACleanup)失敗\n");
    Application->MessageBox(m_msg.c_str(), "ソケットの初期化", MB_ICONINFORMATION | MB_OK);
    return false;
  }
  return true;
}

現状、32回連続で受信した後、上記のWSACleanupで失敗になっています。

このような現象の場合、まずどのあたりを疑うべきでしょうか?
曖昧ですがご教授よろしくお願いします。

A 回答 (2件)

#1 の方の言われるとおりでしょうね。


C++ の言語仕様では、atexit は以下のようになってますから、
32関数以上は失敗しても文句は言えません。
<ISO/IEC14882:2003 18.2.2 C Library>
Implementation Limits: The implementation shall support the registration of at least 32 functions.
</ISO/IEC14882:2003 18.2.2 C Library>

また、extern "C" int atexit(void (*f)(void)) or
extern "C++" int atexit(void (*f)(void))
な関数を呼びだす atexit に int WSACleanup(void) な
関数を渡すと、呼び出し時点で同規格の 5.2.10
Reinterpret cast に抵触して undefined behavior
(未定義動作)になると思われます。
>現実的には動くとしても、規格上は完全に無保証。

せめて、WSACleanup1を呼び出すラッパーをかませるか、
お勧めとしては、それ以前に参照カウント管理をして、
WSAStartup/WSACleanup を最初と最後に一度だけ
呼び出すようにした方がよいと思います。
    • good
    • 0

atexitは32個までしか登録できないのでは?

    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


このQ&Aを見た人がよく見るQ&A