c++ - _Block_Type_Is_Valid (pHead->nBlockUse) 删除堆栈内存?

标签 c++ debugging pointers

<分区>

我知道这是一个常见错误,所以我尝试创建一个最小示例。我认为这是因为我试图释放堆栈内存,但我不太明白如何做不同的事情。

迷宫.h

#pragma once
class Maze
{
    public:
        Maze();
        Maze(unsigned int height, unsigned int width);
        ~Maze();
    private:
        unsigned int m_height;
        unsigned int m_width;
        char *entrance;
        char *exit;
        char *m_cells;
};

迷宫.cpp

#include "Maze.h"
using namespace std;

Maze::Maze()
{
}

Maze::Maze(unsigned int height, unsigned int width) :
    m_height(height),
    m_width(width)
{
    m_cells = new char[m_height * m_width];
    entrance = nullptr;
    exit = nullptr;
}

Maze::~Maze()
{
    delete entrance;
    delete exit;
    delete[] m_cells; //this line causes the error
}

导致错误的main.cpp

#include <iostream>
#include <string>
#include "Maze.h"
using namespace std;

int __cdecl main(int argc, char **argv)
{
    Maze maze;
    maze = Maze(10, 10);
}

没有错误的main.cpp

#include <iostream>
#include <string>
#include "Maze.h"
using namespace std;

int __cdecl main(int argc, char **argv)
{
    Maze maze(10, 10);
}

这两种电源有什么区别?为什么第一个会导致错误?这是一个问题,因为我想声明迷宫但稍后在我的程序中初始化它。在这里我只用两行来创建一个最小的例子。

错误发生在程序关闭时,所以我认为这是一个内存释放问题。确实,当我删除 删除[] m_cells; 从析构函数中,不再有错误。

这里到底发生了什么?

最佳答案

行:

maze = Maze(10, 10);

正在创建对象的拷贝,所以发生的是:

  1. Maze(10, 10) - 构造一个新对象,用 operator new 分配内存和 operator new[] .
  2. maze 被分配了 1 中创建的对象的拷贝。这是通过简单地将第一个对象的指针值分配给第二个对象来完成的。
  3. 然后销毁 1 中的对象,它删除指针。
  4. maze 最终超出范围,它再次删除指针,在这里你崩溃了。

要解决关于 3 规则的阅读,您需要添加一个复制构造函数和一个赋值运算符。

例如:

// This the copy constructor
Maze::Maze(const Maze& other)
{
    // Call the assignment operator, saves duplicating the assignment operator code in here.
    *this = other;
}

// This is the assignment operator 
Maze& Maze::operator = ( const Maze& other )
{
    if ( this != &other )
    {
        // TODO: Copy your pointers, not by assigning them, but use operator new and copy the data as "other" will destruct and delete those pointers, hence your problem
    }
    return *this;
}

如果您使用的是 C++11,您也可以使用移动构造/赋值,那么您只需交换指针,并将源对象指针设置为 NULL/nullptr。

在 C++11 中,您还可以使用 default 和 delete 关键字来防止使用您尚未实现但不应调用的构造函数,例如:

class Foo
{
public:
   Foo() = default;
   // Prevent copying
   Foo(const Foo&) = delete;
   Foo& operator = ( const Foo& ) = delete;
   int x = 0;
};

这会导致以下编译阶段失败:

Foo a;
a = Foo(); 

关于c++ - _Block_Type_Is_Valid (pHead->nBlockUse) 删除堆栈内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23941397/

相关文章:

c++ - 将新运算符应用于数组指针的防错方法

c++ - 复活用 Visual Studio 6 编写的项目

c++ - 文本编辑器 API。用于实验性 IDE 的 Scintilla。你用别的东西吗?

c++ - 为什么静态成员指针在 ELF 部分为零?

javascript - 在不创建 html/javascript 测试文件的情况下在浏览器中测试 JavaScript 脚本

c - 列出对我的库的所有调用

c - POINTER_SIGNED 或 POINTER_UNSIGNED 的用例?

c++ - 在多线程 C/C++ 中,malloc/new 在分配内存时是否锁定堆

c++ - 返回 vector<Foo> 或 shared_ptr<vector<Foo>>?

c++ - GNU 编译器调试 'Level'