-1

我有一个带有字符串键的 AVL 树和我自己的 String 类。为了解决另一个问题,我不得不向 String 添加一个复制构造函数。但是,valgrind 报告了一个错误。这是构造函数:

String::String(const String& s){
    try {
        mStr = new char[1];
    }
    catch (const bad_alloc& e){
        printf("ERROR: No memory\n");
        exit(0);
    }
    mStr[0]='\0';
    mCopy(s);
}

void String::mCopy(const String& s){
    //  delete[] mStr;
    size_t n = s.Length();
    try{
        mStr = new char[n + 1];
    }
    catch (const bad_alloc& e){
        printf("ERROR: No memory\n");
        exit(0);
    }
    strcpy(mStr, s.mStr);
    mStr[n + 1] = '\0';
}

这是向我的 AVL 树添加字符串键后 Valgrind 输出的一部分:

==7005== Invalid write of size 1
==7005==    at 0x4013A1: String::mCopy(String const&) (in /home/ezrafell/Desktop/DA2final/DA3.o)
==7005==    by 0x401213: String::String(String const&) (in /home/ezrafell/Desktop/DA2final/DA3.o)
==7005==    by 0x40182D: main (in /home/ezrafell/Desktop/DA2final/DA3.o)
==7005==  Address 0x5ad450d is 0 bytes after a block of size 61 alloc'd
==7005==    at 0x4C2E80F: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7005==    by 0x40136B: String::mCopy(String const&) (in /home/ezrafell/Desktop/DA2final/DA3.o)
==7005==    by 0x401213: String::String(String const&) (in /home/ezrafell/Desktop/DA2final/DA3.o)
==7005==    by 0x40182D: main (in /home/ezrafell/Desktop/DA2final/DA3.o)

Valgrind 报告的其他错误也可以追溯到operator new[]. String::String(String const&)但它有什么问题呢?以及如何重写构造函数以避免此错误?

4

1 回答 1

3

错误是由这一行产生的:

mStr[n + 1] = '\0';

n+1超过分配的大小。您需要改为使用n,因为字符串的主体位于索引0通过n-1,包括在内,因此索引n是空终止符所在的位置:

mStr[n] = '\0';

注意删除此行也是正确的,因为strcpy空终止其结果。当您使用不适合您的函数时,需要手动放置空终止符,例如memcpy.

于 2017-05-03T10:51:19.703 回答