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,调用堆栈以对HeapAlloc()from的调用结束_heap_alloc。不确定是否重要,但此代码正在 DLL 中调用。

4

1 回答 1

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);

于 2013-03-05T22:17:54.083 回答