删除wchar_t *会导致堆损坏

时间:2014-05-19 09:41:33

标签: c++ mfc heap-corruption

我有这部分代码:

class CNuovoVocabolo {
    CString m_strItaliano;
    CString m_strRusso;
    //...
}

void CNuovoVocabolo::GetVocabolo( CVocabolo* pVocabolo )
{
    int nLIta;
    int nLRus;
    wchar_t *pIta;
    wchar_t *pRus;

    nLIta = m_strItaliano.GetLength();
    nLRus = m_strRusso.GetLength();
    if( nLIta > 0 && nLRus > 0 )
    {
        pIta = new wchar_t[nLIta + 1];
        wcscpy_s( pIta, nLIta * sizeof( wchar_t ), m_strItaliano );
        pRus = new wchar_t[nLRus + 1];
        wcscpy_s( pRus, nLRus * sizeof( wchar_t ), m_strRusso );
        pVocabolo->SetVocabolo( pIta, nLIta, pRus, nLRus );
        delete [] pIta; // *1
        delete [] pRus; // *2
    }
}

// Inside CVocabolo::SetVocabolo:
void CVocabolo::SetVocabolo( const wchar_t* pIta/*=NULL*/, unsigned short nLIta/*=0*/, const wchar_t* pRus/*=NULL*/, unsigned short nLRus/*=0*/ )
{
    if( pIta != NULL && pRus != NULL && nLIta > 0 && nLRus > 0 )
    {
        AzzeraVocabolo();
        m_nLIta = nLIta;
        m_nLRus = nLRus;
        m_pItaliano = new wchar_t[nLIta + 1];
        wcscpy_s( m_pItaliano, nLIta * sizeof( wchar_t ), pIta );
        m_pRusso = new wchar_t[nLRus + 1];
        wcscpy_s( m_pRusso, nLRus * sizeof( wchar_t ), pRus );
    }
}

当我在* 1和* 2处删除pIta指针和pRus指针时,由于堆损坏而导致崩溃。老实说,我不明白为什么会这样,我做错了。有什么建议吗?

修改:
在网上看,我找到了解决方案:

pIta = new wchar_t[( nLIta + 1 ) * sizeof( wchar_t )];

但说实话,对我来说还不清楚。如果你能给我一个解释...... 此外,知道为什么问题被低估了。

1 个答案:

答案 0 :(得分:1)

问题出在这里。

pIta = new wchar_t[nLIta + 1];
wcscpy_s( pIta, nLIta * sizeof( wchar_t ), m_strItaliano );

在第一行中,size是一个宽字符数组加上一个null终止符。这是正确的。

在第二行中,所需的大小是字符数加上null,但是你通过乘法给它一个更大的数字。这是错误的。

如果这些是short个字符和20个字符的字符串,则第一个参数是21,第二个参数是40(它也应该是21)。这本身就是一个无声的错误。不幸的是,在DEBUG构建中(假设您正在使用),wcscpy_s函数填充整个缓冲区,整齐地覆盖未分配的内存。

你的修复工作的原因是你(错误地)使缓冲区足够大以容纳(错误的)长度副本,并且两个wongs变成白色(oops!)。

修复1:删除sizeof的乘法,并为null添加1。

修复2:停止使用这些可怕的函数,并开始使用wstring等编写一些优秀的C ++。

编辑:允许目的地为空。 (糟糕)