Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/148.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在正常块之后检测到堆损坏_C++_Memory_Memory Leaks - Fatal编程技术网

C++ 在正常块之后检测到堆损坏

C++ 在正常块之后检测到堆损坏,c++,memory,memory-leaks,C++,Memory,Memory Leaks,我有下面的代码,不知道为什么在堆损坏检测到错误时,它击中Myclass的析构函数。我相信我正在正确地释放内存 #include <iostream> #include <vector> using namespace std; class MyClass{ private: char* mp_str; public: MyClass():mp_str(NULL){} ~MyClass(){ delete [] mp_str;

我有下面的代码,不知道为什么在堆损坏检测到错误时,它击中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";
}
在main()中,我还添加了

delete a;

在调用return1之前

您需要分配字符串的长度+1,以说明空值。你把它设置好了

if(!this->mp_str){
    this->mp_str = new char[len+1];
    memset(mp_str, 0, len+1);
}
(在拉斐尔的回答被接受后发布,这是应该的。)

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

但是,坚持小跑的另一种方法是根本不需要实现这些事情。在这种情况下,使用
std::string
而不是
char*
可以解决崩溃和小跑兼容问题:

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)";
    }
};
class-MyClass{
私人:
std::字符串mp_str;
公众:
void setString(const char*str){mp_str=str?str:;}
void printString(){

如果(mp_str.size())std::我不需要。@yurikilochek:同意。修复了这个问题。@user315052:是的,我知道
a
的一个副本被推到向量上,我需要一个深度副本。我应该遵循三的规则。但是,代码不应该抛出这样的错误。Rafael的回答帮助我指出了错误!@brainydexter:如果我确定它是根c因为你的崩溃,我会发布一个答案。作为评论,这表明你应该遵循一个建议(因为如果不修复,以后会导致类似的头痛)。Regards@user315052我感谢你发布链接(因此+1:)指引我正确的方向。我意识到这里发生了肤浅的复制,这应该得到纠正。在我继续做这件事之前,我在脑子里想,为什么这该死的东西在我身上哭泣和撞击。:)len+1把我带到了那里!不过,谢谢!我同意@Rafael!唉,我没看到这个:(@brainydexter请注意,这并不是唯一的错误。请参阅上面的评论(应该是答案)Yes and I(re)阅读你发布的TROT链接。我已经有一段时间没有练习过指针的乐趣了,所以我想我应该再次尝试一下这些东西。使用像string这样的类确实让你的生活变得简单。尽管有时你必须编写原始C!@BrianReinhold:智能指针比原始指针更可取,并且仍然会让代码保持兼容。
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)";
    }
};