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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11676259/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 15:24:21  来源:igfitidea点击:

Heap corruption detected after normal block

c++memorymemory-leaks

提问by brainydexter

I have the following code and am not sure why am I getting the heap corruption detected error when it hits the destructor of Myclass. I believe I am deallocating the memory properly ??

我有以下代码,但不确定为什么在遇到 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";
}

EDIT: (Fixed code)

编辑:(固定代码)

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);
}

in main(), I also added

在 main() 中,我还添加了

delete a;

before calling return 1;

在调用 return 1 之前;

回答by Rafael Baptista

You need to allocate the length of the string +1, to account for the null. You are memsetting it right.

您需要分配字符串的长度 +1,以解决空值。你是对的。

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

回答by jxh

(Posted after Rafael's answer was accepted, as it should be.)

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

The buffer overrun was definitely the root cause of this particular crash, but the crash could have been avoided by simplifying the implementation while adjusting for adherence to the Rule of Three. To wit, since you implemented a destructor (to deal with mp_str), you should also have implemented a copy constructor and an assignment operator.

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

But, another way to adhere to TRoT is to avoid needing to implement any of those things at all. In this case, using a std::stringinstead of a char *would have solved both the crash and be TRoT compliant:

但是,遵守 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)";
    }
};