2013-04-22 86 views
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(也简单解释了为什么这会导致堆损坏会有很大帮助)。

+0

那是生产代码吗? – trojanfoe 2013-04-22 15:17:57

+3

使用'std :: string'句号!摆脱所有的指针嘟嘟混杂。 – 2013-04-22 15:18:33

+0

在whilte循环中,它是* psz2 =='0'?或者你的意思是* psz2 ==''0' – Ali 2013-04-22 15:19:16

回答

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会更加清楚和简单。

+0

'* pstr = psz2;'? CString'支持那个吗?罗。 – trojanfoe 2013-04-22 15:21:03

+0

@trojanfoe,船长无知我没有那么深入的了解这个功能。我会相应地重新解释我的答案。 – simonc 2013-04-22 15:22:06

+0

'psz2 = psz1;'这并不意味着'psz2'指向'psz1',这只是'新'了吗? – 2013-04-22 15:25:09

2

从MSDN:

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

在这里,在你的代码,你是一个未初始化数组上调用strlen,你需要修复它(通过元素的目标缓冲区可存放的最大数量):

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

难道你不是只复制bug strlen(psz2)作为长度参数strcpy_s()? – harper 2013-04-22 15:28:37

+1

是的,我在这里显示了错误的确切路线,没有显示错误修正(作为练习留给读者 - 应该很容易,真的)。 – piokuc 2013-04-22 15:31:14