メモリの割り当てと解放について

解決


どら  2005-02-17 22:10:16  No: 56469

本当に毎度すみません・・・。

先日、ローカルホストのアドレスやDHCPか固定かなどの関数の情報をいただきました(maxwellさん多謝)。

その関数を色々調べ

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/iphlp/iphlp/getadaptersinfo.asp

などをもとに、そのPCの n 枚目のネットワークアダプタの情報を取れる関数を作って見ています。
ソースはしたの通りです。

BOOL GetLANIFInfo(PIP_ADAPTER_INFO pifInfo, int count)
{
  int aCount;
  DWORD dwResult;
  PIP_ADAPTER_INFO pAdInfo = NULL;
  ULONG szpAdInfo = sizeof(IP_ADAPTER_INFO);

  //メモリ領域を確保
  pAdInfo = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO));

  //バッファの大きさを見て、足りない場合は、もう一回領域を確保
  dwResult = GetAdaptersInfo(pAdInfo, &szpAdInfo);
  if(dwResult == ERROR_BUFFER_OVERFLOW)
  {
    free(pAdInfo);
    pAdInfo = (IP_ADAPTER_INFO *)malloc(szpAdInfo);
  }
  //アダプタ情報がない場合は、そのまま終了
  else if(dwResult == ERROR_NO_DATA)
  {
//    MessageBox(NULL, "対応するネットワークアダプタ無し", "デバッグ", MB_OK);
    return FALSE;
  }
  //アダプタ情報をゲット
  dwResult = GetAdaptersInfo(pAdInfo, &szpAdInfo);
  if(dwResult != ERROR_SUCCESS)
  {
//    MessageBox(NULL, "GetAdaptersInfo実行エラー", "デバッグ", MB_OK);
    return FALSE;
  }
  
  aCount = 1;
  while(1)
  {
    //count個目の情報になったら情報をコピーしてTRUEを返す
    if(aCount == count)
    {
      strcpy(pifInfo->AdapterName, pAdInfo->AdapterName);
      for(int x = 0; x < MAX_ADAPTER_ADDRESS_LENGTH; x++)
      {
        pifInfo->Address[x] = pAdInfo->Address[x];
      }
      pifInfo->AddressLength = pAdInfo->AddressLength;
      pifInfo->ComboIndex = pAdInfo->ComboIndex;
      pifInfo->CurrentIpAddress = pAdInfo->CurrentIpAddress;
      strcpy(pifInfo->Description, pAdInfo->Description);
      pifInfo->DhcpEnabled = pAdInfo->DhcpEnabled;
      pifInfo->DhcpServer = pAdInfo->DhcpServer;
      pifInfo->GatewayList = pAdInfo->GatewayList;
      pifInfo->HaveWins = pAdInfo->HaveWins;
      pifInfo->Index = pAdInfo->Index;
      pifInfo->IpAddressList = pAdInfo->IpAddressList;
      pifInfo->LeaseExpires = pAdInfo->LeaseExpires;
      pifInfo->LeaseObtained = pAdInfo->LeaseObtained;
      pifInfo->PrimaryWinsServer = pAdInfo->PrimaryWinsServer;
      pifInfo->SecondaryWinsServer = pAdInfo->SecondaryWinsServer;
      pifInfo->Type = pAdInfo->Type;
      break;
    }
    else
    {
      aCount++;
      pAdInfo = pAdInfo->Next;
      if(pAdInfo == NULL)
      {
        free(pAdInfo);
        pAdInfo = NULL;
//        MessageBox(NULL, "指定した数のネットワークアダプタがありません", "デバッグ", MB_OK);
        return FALSE;
      }
    }

  }
  if(pAdInfo != NULL)
  {
//    MessageBox(NULL, "ここまではOK", "デバッグ", MB_OK);
    free(pAdInfo);
    pAdInfo = NULL;
  }

  return TRUE;
}

そして、ダイアログプロシージャで、OKボタンを押されたとき、ネットワークアダプタのあるうち、つまりこの関数がFALSEを返していないときはこの関数から値を取り続けるようにしてみました(下記ソース)

IP_ADAPTER_INFO ai;
int n;

for(n = 1;;n++)
{
  if(GetLANIFInfo(&ai, n)==FALSE)
  {
    MessageBox(hDlg, "情報の取得に失敗", "残念っ!!", MB_OK);
    break;
  }
  //取得した情報を適当に処理する関数
}

といった感じです。
これで実行してみると、ループのうち1回目は問題なく動作するのですが、2回目に関数を実行すると、エラーがでてとまってしまうんです。

どこがおかしいかデバッグしてみると・・・
どうやら2回目に関数を呼び出したときの最後のfreeの所でつまずいているみたいです。

単純にC言語の話題になってしまっているかもしれないんですが、同一関数を何度も呼び出すときは、メモリの確保・解放に何か工夫を施さなければならないのでしょうか?

どなたかご存じの方、ご教授いただけないでしょうか?
よろしくお願いします・・・。


REE  2005-02-17 22:33:22  No: 56470

pAdInfo = pAdInfo->Next;

ここで、pAdInfo がmallocしたときとは違うものになっているため、
freeで失敗します。


どら  2005-02-17 22:45:16  No: 56471

・・・あ、なるほど。
確かにおっしゃるとおりですね >REEさん

そうなると、ここで割り当てられたメモリの領域をすべて解放するには、どの様にすればよいのでしょうか?
何か特殊な関数が必要なのでしょうか??


maxwell  2005-02-17 23:16:56  No: 56472

while(1)のループに入る前に
PIP_ADAPTER_INFO pBackup = pAdInfo;
としておいて
free(pBackup)
でどうでしょうか?


どら  2005-02-18 01:51:52  No: 56473

ありがとうございます。
解決です。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加