堆分配问题

Heap allocation problems

本文关键字:问题 分配      更新时间:2023-10-16

当我试图在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_alloc调用HeapAlloc()结束。不确定是否重要,但此代码正在DLL中调用

看起来我能够通过将CMD5::HexHash()函数更改为

来解决内存分配问题
    void HexHash(CString &strHash) {
        for (int i=0; i<16; i++)
            strHash += StringFormat(_T("%02X"), m_szHash[i]);
        return;
    }

并通过cMD5.HexHash(strHashHex);

调用