5

我有以下代码,但不确定为什么在遇到 Myclass 的析构函数时会收到堆损坏检测错误。我相信我正在正确地释放内存??

#include <iostream>
#include <vector>
using namespace std;

class MyClass{
private:
    char* mp_str;
public:
    MyClass():mp_str(NULL){}
    ~MyClass(){
        delete [] mp_str;
    }

    void setString(const char* str);
    void printString();
};

int main(){
    MyClass* a = new MyClass();
    std::vector<MyClass> myVector;

    myVector.push_back(*a);

    a->setString("Hello World");
    myVector[0].setString("Goodbye world");

    a->printString();
    myVector[0].printString();

    return 1;
}

void MyClass::setString(const char* const str){
    if(!str)
        return;

    size_t len = strlen(str);

    if(!this->mp_str){
        this->mp_str = new char[len];
        memset(mp_str, 0, len+1);
    }
    strncpy(mp_str, str, len);
}

void MyClass::printString(){
    if(this->mp_str)
        cout << mp_str;
    else
        cout << "No string found";
}

编辑:(固定代码)

void MyClass::setString(const char* const str){
    if(!str)
        return;

    size_t len = strlen(str);

    if(!this->mp_str){
        this->mp_str = new char[len+1];
        memset(mp_str, 0, len+1);
    }
    strncpy(mp_str, str, len);
}

在 main() 中,我还添加了

delete a;

在调用 return 1 之前;

4

2 回答 2

8

您需要分配字符串 +1 的长度,以考虑空值。你是正确的。

if(!this->mp_str){
    this->mp_str = new char[len+1];
    memset(mp_str, 0, len+1);
}
于 2012-07-26T19:03:49.683 回答
1

(在拉斐尔的回答被接受后发布,应该是这样。)

缓冲区溢出绝对是这次特定崩溃的根本原因,但可以通过简化实现同时调整遵守三规则来避免崩溃。也就是说,既然您实现了一个析构函数(处理mp_str),那么您还应该实现一个复制构造函数和一个赋值运算符。

但是,坚持 TRoT 的另一种方法是完全避免需要实施任何这些事情。在这种情况下,使用 astd::string而不是 achar *将解决崩溃并符合 TRoT:

class MyClass{
private:
    std::string mp_str;
public:
    void setString(const char* str) { mp_str = str ? str : ""; }
    void printString() {
        if (mp_str.size()) std::cout << mp_str;
        else std::cout << "(mp_str is empty)";
    }
};
于 2012-07-26T19:34:30.850 回答