2

所以我是 C++ 的一个相当大的新人,所以我确信这是一个相对简单的问题,但是我有一个遗留的 C++ 应用程序我正在尝试跟踪堆损坏问题并将其跟踪到这个函数:

void LTrimZeros(CString *pstr)
{
    char *psz1;
    char *psz2;

    if ( pstr->GetLength() == 0 )
        return;


    psz1 = new char[pstr->GetLength() + 1];
    psz2 = psz1;

    strcpy_s( psz2, strlen(psz2), (const char *) *pstr );

    while ( *psz2 == '0' )
    {
        psz2++;
    }

    *pstr = psz2;

    delete [] psz1;

    return;
}

当它尝试删除psz1时,会引发堆损坏错误。再说一次,我对 C++ 还是很陌生,所以我不想尝试解决这个问题并意外引入内存泄漏,所以我想我会问专家。相同功能的替代解决方案也很好,因为这个应用程序最初是用 c++4 编写的,但现在升级到 c++11(简要解释为什么这会导致堆损坏会有很大帮助)。

4

2 回答 2

3

strlen(psz2)正在读取未初始化的内存,因此可能会超出数组的末尾。这意味着您传递给的长度strcpy_s将是不可预测的,并且可能导致您写入超出为psz1.

假设您的函数的结尾是有效的(我对CString不太熟悉可以肯定地说),您可以简单地将您的strcpy_s行更改为

strcpy_s( psz2, pstr->GetLength() + 1, (const char *) *pstr );

您可能会在使用 win32 字符串处理函数时遇到问题,这些函数根据UNICODE_UNICODE定义在 8 位和 16 位字符之间切换。我同意 Alok Save 和其他人的观点,即切换到使用std::string会更清晰、更简单。

于 2013-04-22T15:19:32.540 回答
2

来自 MSDN:

errno_t strcpy_s(
   char *strDestination,
   size_t numberOfElements,
   const char *strSource 
);

在这里,在您的代码中,您正在调用strlen一个未初始化的数组,您需要修复它(传递目标缓冲区可以存储的最大元素数):

strcpy_s( psz2, strlen(psz2), (const char *) *pstr );
于 2013-04-22T15:21:03.607 回答