2013-03-05 76 views
1

我遇到內存不足的錯誤,當我嘗試在Visual Studio 2012年我在想,這個代碼是起因運行我的C++程序(因爲當我刪除它,它運行良好):堆分配問題

void GetMachineHash(CString &strHashHex) { 
    CMD5 cMD5; 
    BYTE *szHash = (BYTE*)malloc(48); 
    LPBYTE szMachineNameHash, szNetworkAddressHash, szVolumeIdHash; 

    TCHAR szMachineId[100]; 
    DWORD nMachineIdLen = 100; 

    TCHAR szNetworkAddress[13]; 
    IP_ADAPTER_INFO *pAdapterInfo, *pAdapter = NULL; 
    DWORD dwRetVal = 0; 
    ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO); 

    TCHAR szVolumeId[20]; 
    TCHAR szVolumeName[MAX_PATH]; 
    TCHAR szFileSystemName[MAX_PATH]; 
    DWORD dwSerialNumber = 0; 
    DWORD dwMaxComponentLen = 0; 
    DWORD dwFileSystemFlags = 0; 

    ZeroMemory(szHash, 48); 
    ZeroMemory(szMachineId, 100); 
    ZeroMemory(szVolumeId, 20); 
    ZeroMemory(szVolumeName, MAX_PATH); 
    ZeroMemory(szFileSystemName, MAX_PATH); 
    ZeroMemory(szNetworkAddress, 13); 

    GetComputerName(szMachineId, &nMachineIdLen); 

    cMD5.Calculate(szMachineId); 
    szMachineNameHash = cMD5.Hash(); 

    pAdapterInfo = (IP_ADAPTER_INFO *) malloc(sizeof(IP_ADAPTER_INFO)); 
    if (pAdapterInfo == NULL) { 
      TRACE(_T("Error allocating memory needed to call GetAdaptersinfo()")); 
      szNetworkAddressHash = NULL; 
    } 

    // Make an initial call to GetAdaptersInfo to get the necessary size into the ulOutBufLen variable 
    if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) { 
      free(pAdapterInfo); 
      pAdapterInfo = (IP_ADAPTER_INFO *)malloc(ulOutBufLen); 

      if (pAdapterInfo == NULL) { 
        TRACE(_T("Error allocating memory needed to call GetAdaptersinfo()")); 
        szNetworkAddressHash = NULL; 
      } 
    } 

    if ((dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR) { 
      pAdapter = pAdapterInfo; 

      while (pAdapter) { 
        if (pAdapter->Type != MIB_IF_TYPE_LOOPBACK) { 
          _stprintf_s(szNetworkAddress, 13, _T("%.2X%.2X%.2X%.2X%.2X%.2X"), 
            pAdapter->Address[0], 
            pAdapter->Address[1], 
            pAdapter->Address[2], 
            pAdapter->Address[3], 
            pAdapter->Address[4], 
            pAdapter->Address[5] 
          ); 

          break; 
        } 

        pAdapter = pAdapter->Next; 
      } 
    } else { 
      TRACE(_T("GetAdaptersInfo() call failed")); 
      szNetworkAddressHash = NULL; 
    } 

    cMD5.Calculate(szNetworkAddress); 
    szNetworkAddressHash = cMD5.Hash(); 

    if (GetVolumeInformation(
      NULL, 
      szVolumeName, 
      sizeof(szVolumeName), 
      &dwSerialNumber, 
      &dwMaxComponentLen, 
      &dwFileSystemFlags, 
      szFileSystemName, 
      sizeof(szFileSystemName))) { 
        _stprintf_s(szVolumeId, 20, _T("%lu"), dwSerialNumber); 
    } 

    cMD5.Calculate(szVolumeId); 
    szVolumeIdHash = cMD5.Hash(); 

    // Calculate hash from hashes 
    memcpy(szHash, szMachineNameHash, 16); 
    memcpy(szHash+16, szNetworkAddressHash, 16); 
    memcpy(szHash+32, szVolumeIdHash, 16); 

    cMD5.Calculate(szHash, 48); 

    strHashHex.Preallocate(33); 
    strHashHex = cMD5.HexHash(); 

    free(szHash); 
    free(pAdapterInfo); 

    return; 
} 

然後,如果我離開這個功能,只是刪除此代碼:

strHashHex.Preallocate(33); 
    strHashHex = cMD5.HexHash(); 

然後,它會正常工作爲好。所以我想知道如果這是導致內存問題的代碼,如果是,我該如何解決它?

這裏的CMD5類(它利用Windows的API生成一個MD5總和):

class CMD5 
{ 
public: 
    CMD5() { 
     if(CryptAcquireContext(&m_hCryptProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET) == 0){ 
      if(GetLastError() == NTE_EXISTS){ 
       CryptAcquireContext(&m_hCryptProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0); 
      } 
     } 
    } 

    ~CMD5() { 
     if(m_hCryptProv) 
      CryptReleaseContext(m_hCryptProv, 0); 
     m_hCryptProv = NULL; 
     free(m_szHash); 
    } 

    bool Calculate(LPCTSTR szText) { 
     DWORD dwLen = sizeof(TCHAR) * _tcslen(szText); 
     DWORD dwHashLen; 
     DWORD dwHashLenSize = sizeof(DWORD); 

     if (CryptCreateHash(m_hCryptProv, CALG_MD5, 0, 0, &m_hHash)) { 
      if (CryptHashData(m_hHash, (const BYTE*)szText, dwLen, 0)) { 
       if (CryptGetHashParam(m_hHash, HP_HASHSIZE, (BYTE *)&dwHashLen, &dwHashLenSize, 0)) { 
        if(m_szHash = (BYTE*)malloc(dwHashLen)) { 
         if (CryptGetHashParam(m_hHash, HP_HASHVAL, (BYTE*)m_szHash, &dwHashLen, 0)) { 
          CryptDestroyHash(m_hHash); 
         } 
        } 
       } 
      } 
     } 

     return false; 
    } 

    bool Calculate(const LPBYTE szText, DWORD dwLen) { 
     DWORD dwHashLen; 
     DWORD dwHashLenSize = sizeof(DWORD); 

     if (CryptCreateHash(m_hCryptProv, CALG_MD5, 0, 0, &m_hHash)) { 
      if (CryptHashData(m_hHash, (const BYTE*)szText, dwLen, 0)) { 
       if (CryptGetHashParam(m_hHash, HP_HASHSIZE, (BYTE *)&dwHashLen, &dwHashLenSize, 0)) { 
        if(m_szHash = (BYTE*)malloc(dwHashLen)) { 
         if (CryptGetHashParam(m_hHash, HP_HASHVAL, (BYTE*)m_szHash, &dwHashLen, 0)) { 
          CryptDestroyHash(m_hHash); 
         } 
        } 
       } 
      } 
     } 

     return false; 
    } 

    LPBYTE Hash() const { 
     LPBYTE szHash = new BYTE[16]; 

     ZeroMemory(szHash, 16); 

     memcpy(szHash, m_szHash, 16); 

     return szHash; 
    } 

    LPTSTR HexHash() const { 
     LPTSTR szBuf = new TCHAR[33]; 

     ZeroMemory(szBuf, 33); 

     for (int i=0; i<16; i++) 
      _stprintf_s(szBuf+i*2, 33, _T("%02X"), m_szHash[i]); 

     szBuf[32]=0; 

     return szBuf; 
    } 
private: 
    BYTE *m_szHash; 
    DWORD m_hHash; 
    HCRYPTPROV m_hCryptProv; 
}; 

另外,我從VS2012得到的錯誤是Critical error detected c0000374和調用堆棧與_heap_allocHeapAlloc()通話結束。不知道它是否重要,但在DLL中調用此代碼。

+0

你能張貼[SSCCE]稱它爲( http://sscce.org)?該代碼太長,以至於我懷疑任何人都會通讀它來發現您的問題。我只能猜測:由於刪除對'Preallocate'的調用可以讓你的問題消失,你確定你釋放了你在那裏分配的內存嗎? (看看RAII和智能指針)還可以考慮使用分析器來告訴你memleaks在哪裏。 – 2013-03-05 07:49:34

+0

你只需要調用一次或多次該代碼?在第一種情況下,它可能是內存損壞問題,第二種情況是內存泄漏。你能否創建一個簡單的例子來重現問題,只需發佈​​代碼?您也可以嘗試使用MS的應用程序驗證器。 – Philipp 2013-03-05 07:51:48

+0

我有多年沒有使用CString - 有可能是'strHashHex.Preallocate(33); strHashHex = cMD5.HexHash();'分配內存兩次,'cMD5.HexHash()'中分配的內存永遠不會被釋放? – Philipp 2013-03-05 07:54:19

回答

0

它看起來像我能夠通過改變CMD5 :: HexHash()函數來解決內存分配問題

void HexHash(CString &strHash) { 
     for (int i=0; i<16; i++) 
      strHash += StringFormat(_T("%02X"), m_szHash[i]); 

     return; 
    } 

,並通過cMD5.HexHash(strHashHex);