2016-12-07 2 views
0

Этого кода, при использовании в Builder Embarcadero C++ 2009, сборки «Release», по-видимому, развращают память:код, чтобы получить MAC-адрес, кажется, повреждение памяти, но только в сборке Release, а не Debug строить

String MyCode::MacAddress(bool Dashes, DWORD *Index) 
{ 
// Dashes to build the string with dashes or not: 00-14-22-01-23-45 vs. 001422

// Index is Input and Output. 
// If NULL or Index==0 the first Mac address is requested. 
// If > 0 that mac address is requested (0 based index) 
// The return value, if !NULL, is always the count of available mac addresses 

String Address ; 

DWORD (*MyGetAdaptersInfo)(PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen) = NULL ; 
HMODULE khand = NULL ; 
DWORD GetIndex = (Index)?(*Index):(0) ; 
if (Index) *Index = 0 ; 

if (!khand) 
    { 
    khand = LoadLibrary(TEXT("Iphlpapi.dll")) ; 

    if (khand) 
     { 
     MyGetAdaptersInfo = (DWORD (*)(PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen)) GetProcAddress(khand, "GetAdaptersInfo") ; 
     } 
    } 

if (MyGetAdaptersInfo) 
    { 
    DWORD MacBufLen = 0 ; 
    IP_ADAPTER_INFO IPInfo ; 
    MyGetAdaptersInfo(&IPInfo, &MacBufLen) ; 
    if (MacBufLen) 
     { 
     BYTE *Buffer = new BYTE[MacBufLen] ; 
     if (Buffer) 
      { 
      IP_ADAPTER_INFO *IPInfo = (IP_ADAPTER_INFO*)Buffer ; 
      if (MyGetAdaptersInfo(IPInfo, &MacBufLen) == ERROR_SUCCESS) 
       { 
       DWORD Cnt = (MacBufLen/sizeof(IP_ADAPTER_INFO)) ; 
       if (Index) *Index = Cnt ; 
       if (GetIndex < Cnt) 
        { 
        IPInfo = (IP_ADAPTER_INFO*) &Buffer[(GetIndex * sizeof(IP_ADAPTER_INFO))] ; 
        for (DWORD x = 0 ; x < IPInfo->AddressLength ; x++) 
         { 
         if (!Dashes || x == (IPInfo->AddressLength - 1)) 
          { 
          Address += String().sprintf(L"%.2X", (int)IPInfo->Address[x]) ; 
          } 
         else 
          { 
          Address += String().sprintf(L"%.2X-", (int)IPInfo->Address[x]) ; 
          } 
         } 
        } 
       } 
      } 
     delete[] Buffer ; 
     } 
    } 

FreeLibrary(khand) ; 

return Address ; 
} 

Вы видите, что я сейчас не могу видеть?

Я использовал этот код какое-то время в отладочных сборках без проблем. Поэтому я никогда не сомневался в его правильном функционировании. Но теперь, когда я построил версию выпуска, используя Embarcadero C++ Builder 2009, она, похоже, повреждает память других функций, вызываемых впоследствии, что в конечном итоге приводит к ошибке исключения.

Когда я удаляю вызов MacAddress() из кода, все работает как шарм снова.

В режиме отладки CodeGuard никогда не запускался.

Ваш вклад оценили

+4

Вызов конвенции отсутствует. Это '__stdcall' (или' WINAPI', если вы предпочитаете макросы win32). –

+0

Я замечаю эту строку: if (! Khand) Кажется ненужным, так как khand инициализируется значением NULL. Вы называете эту функцию рекурсивно? – SmittyBoy

+1

[Что может пойти не так, когда вы не согласны с вызывающим соглашением?] (Https://blogs.msdn.microsoft.com/oldnewthing/20040115-00/?p=41043) – IInspectable

ответ

2

Вы не объявляя соглашение о вызовах для MyGetAdaptersInfo переменной, поэтому по умолчанию компилятора (обычно __cdecl) используется. Но функция GetAdaptersInfo() (как и большинство Win32 API) использует соглашение о вызове __stdcall, поэтому вам нужно включить это в свою декларацию.

Кроме того, вы не должны полагаться на sizeof(IP_ADAPTER_INFO). Его размер может измениться с одной версии ОС на другую, и нет возможности узнать, какой размер использует данная версия. IP_ADAPTER_INFO реализован как связанный список (даже если он выделен как один непрерывный буфер памяти), вам нужно правильно пройти список, используя поле IP_ADAPTER_INFO::Next.

Попробуйте что-то больше, как это:

String MyCode::MacAddress(bool Dashes, DWORD *Index) 
{ 
    // Dashes to build the string with dashes or not: 00-14-22-01-23-45 vs. 001422

    // Index is Input and Output. 
    // If NULL or Index==0 the first Mac address is requested. 
    // If > 0 that mac address is requested (0 based index) 
    // The return value, if !NULL, is always the count of available mac addresses 

    String Address; 

    typedef DWORD (WINAPI *LPFN_GetAdaptersInfo)(PIP_ADAPTER_INFO, PULONG); 

    DWORD GetIndex = (Index) ? *Index : 0; 
    if (Index) *Index = 0; 

    HMODULE khand = LoadLibrary(TEXT("Iphlpapi.dll")); 
    if (khand) 
    { 
     LPFN_GetAdaptersInfo MyGetAdaptersInfo = (LPFN_GetAdaptersInfo) GetProcAddress(khand, "GetAdaptersInfo"); 
     if (MyGetAdaptersInfo) 
     { 
      DWORD MacBufLen = 0; 
      if ((MyGetAdaptersInfo(NULL, &MacBufLen) == ERROR_BUFFER_OVERFLOW) 
       && (MacBufLen > 0)) 
      { 
       DynamicArray<BYTE> Buffer; // or std::vector<BYTE> 
       Buffer.Length = MacBufLen; 

       PIP_ADAPTER_INFO IPInfo = (PIP_ADAPTER_INFO) &Buffer[0]; 
       if (MyGetAdaptersInfo(IPInfo, &MacBufLen) == ERROR_SUCCESS) 
       { 
        DWORD Cnt = 0; 
        do 
        { 
         if (GetIndex == Cnt) 
         { 
          for (DWORD x = 0; x < IPInfo->AddressLength; ++x) 
          { 
           if (!Dashes || (x == (IPInfo->AddressLength - 1))) 
           { 
            Address += String().sprintf(L"%.2X", (int) IPInfo->Address[x]); 
           } 
           else 
           { 
            Address += String().sprintf(L"%.2X-", (int) IPInfo->Address[x]) ; 
           } 
          } 
         } 

         ++Cnt; 
         IPInfo = IPInfo->Next; 
        } 
        while (IPInfo != NULL); 

        if (Index) *Index = Cnt; 
       } 
      } 
     } 

     FreeLibrary(khand); 
    } 

    return Address; 
}