字符串运算符和valgrind

时间:2017-03-30 22:55:16

标签: c++ valgrind

我在正确写入方法时遇到了一些问题: 编辑我写了新的可能很好

void operator += ( const string& s )
{
    size_t newLen = len + s.len;
    char    *tmpStr = new char [newLen+1];
    size_t i = 0;
    for(i;i<len;i++)
        {tmpStr[i] = p[i];}
    for(size_t j=0;j<s.len;j++)
    {
    tmpStr[i] = s[j];
    i++;
    }
    delete []p;
    p = tmpStr;
    len = newLen;
    p[len] = '\0';
}

Valgrind回复我,我得到了一些错误和1个内存泄漏

HEAP SUMMARY:
==10152==     in use at exit: 72,704 bytes in 1 blocks
==10152==   total heap usage: 5 allocs, 4 frees, 73,747 bytes 
allocated

==10152== LEAK SUMMARY:
==10152==    definitely lost: 0 bytes in 0 blocks
==10152==    indirectly lost: 0 bytes in 0 blocks
==10152==      possibly lost: 0 bytes in 0 blocks
==10152==    still reachable: 72,704 bytes in 1 blocks
==10152==         suppressed: 0 bytes in 0 blocks
==10152== Reachable blocks (those to which a pointer was found) are 
not shown.
==10152== To see them, rerun with: --leak-check=full --show-leak-
kinds=all

==10152== For counts of detected and suppressed errors, rerun with: -v
==10152== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

我试过它:

string s2 = "hello";
string s3 = "abc";
s3 += s2;

我的下一个问题是如何写,任何想法我必须做什么?

void operator += ( char c );

这是你的构造函数:

string( )
  : len{0},
    p{ nullptr }   
{ }

string( const char* s )
  : len{ strlen(s) },
    p{ new char[ len ] }
{
  for( size_t i = 0; i < len; ++ i )
     p[i] = s[i]; 
}

string( const string& s )
  : len{ s. len },
    p{ new char[ len ] }
{
  for( size_t i = 0; i < len; ++ i )
     p[i] = s.p[i]; 
}

正确:泄漏内存仍然可以访问:1个块中72,704个字节

2 个答案:

答案 0 :(得分:0)

指出的两个错误让我认为std::string *正在为内部strcpy类型的缓冲区分配内存。 (因为它追求string的5个字节和"hello"的3个字节。)

"abc"是一个不安全的操作,它会一直运行,直到找到strcpy终结符。现在看来你的\0类型的内部缓冲区似乎没有考虑这个,假设像

这样的东西
string

由于没有char data[] = {'h', 'e', 'l', 'l', 'o'}; ,因此不会为strcpy工作。向我们展示如何构建\0实例。

既然您已经编辑了问题清楚的问题,那么构造函数不会保留空间,也不会将NUL终结符放在string的末尾,因此标准的stdlib函数是如果不能正常工作,请尝试以下方法:

char[]

这里的区别在于您为缓冲区分配string( const char* s ) : len{ strlen(s) }, p{ new char[ len+1 ] } { for( size_t i = 0; i < len; ++ i ) p[i] = s[i]; p[len] = '\0'; } 字符并将len+1放在数组的最后一个元素中。

此终结符适用于stdlib函数,以便他们知道停止的位置。现在\0在找到终结符时会正常工作。

答案 1 :(得分:0)

构造函数没有在p数组中放置一个尾随空字节,这是任何strXXX()函数所需的。分配数组时,需要将1添加到len。然后使用strcpy()初始化p数组,该数组将复制所有字符和空字节。

string( const char* s )
  : len{ strlen(s) },
    p{ new char[ len+1 ] }
{
  strcpy(p, s);
}

string( const string& s )
  : len{ s. len },
    p{ new char[ len + 1 ] }
{
  strcpy(p, s.p);
}

另外,+=功能需要检查是否p == nullptr,而不是在这种情况下调用strcpy()

void operator += ( const string& s )
{
    size_t newLen = len + s.len;
    if (newLen == 0) { // Appending empty string to empty string, nothing to do
        return;
    }
    char *tmpStr = new char [newLen+1];
    if (p) {
        strcpy(tmpStr, p);
    }
    if (s.p) {
        strcpy(tmpStr + len, s.p);
    }
    delete []p;
    p = tmpStr;
    len = newLen;
}