堆分配问题

时间:2013-03-05 07:32:34

标签: c++ visual-c++ memory-management visual-studio-2012 heap

当我尝试在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,调用堆栈以HeapAlloc()_heap_alloc的调用结束。不确定它是否重要但是这个代码是在DLL中调用的。

1 个答案:

答案 0 :(得分: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);

进行调用