CRT 检测到应用程序在堆缓冲区(新建/删除)类结束后写入内存

Posted

技术标签:

【中文标题】CRT 检测到应用程序在堆缓冲区(新建/删除)类结束后写入内存【英文标题】:CRT detected that the application wrote to memory after end of heap buffer (new/delete) classes 【发布时间】:2017-03-29 16:00:01 【问题描述】:

我收到“调试错误”CRT 检测到应用程序在堆结束后写入内存。但我不明白为什么,也找不到任何类似的例子。

完整的代码是... 虽然我认为这可能只是 main 的问题。

#include <iostream>
#include <cmath>
#include <array>

using namespace std;
// Declare global consts
const double pi = 3.1415926583;


// Base class Shape
class Shape
protected:
    double *sides;
public:
    Shape(const int n) //parameterized for n dimensional shape
    sides = new double[n];

// need virtual destructor
virtual ~Shape()
    delete[] sides;

virtual double area() const = 0; // pure virtual function for area
virtual double volume() const = 0; // pure virtual function for volume
;

//////////////////////////////////////////////////////////
//Derived classes for 2D and 3D Shapes
class Shape2D : public Shape // inherit shape
protected:
    int n = 2; //n denotes the number of dimensions
public:
    // default constructor
    Shape2D() :Shape(n)
    // param constructor
    Shape2D(const double side1, const double side2) :Shape(n)
        sides[0] = side1; sides[1] = side2;
    
    virtual ~Shape2D() //virtual destructor
    double volume() const  cout << "trying to calculate volume of 2d   shape..." << endl; return 0; ;
;

/////////////////////////////////////////////////////////////////////
//2D shapes
class Rectangle : public Shape2D
public:
    // constructors
    Rectangle() :Shape2D() 
    Rectangle(const double side1, const double side2) :Shape2D(side1, side2)
    ~Rectangle()
    double area() const  return (sides[0] * sides[1]); 
;

int main()
    Shape **ShapePointer = new Shape*[2];
    ShapePointer[0] = new Rectangle(2, 5);
    ShapePointer[1] = new Rectangle(1, 3);
    // clean up 
    delete ShapePointer[0];
    delete ShapePointer[1];
    delete[] ShapePointer;
    system("pause");
    return 0;

【问题讨论】:

在一个不相关的(也许)我认为不需要ShapePointer。只需有一个指向Shape 的普通指针数组,如Shape* ShapeArray[2] = new Rectangle(...), new Rectangle(...) 谢谢,我最初尝试过,但遇到了这个问题。 与您的问题更相关,您不能在调试器中运行并在运行程序时捕获错误吗?然后你应该能够在你的代码中找到它发生的位置。或者至少添加大量调试日志来帮助您缩小范围? double *sides; -- 只需使用std::vector&lt;double&gt; sides;,因为您的Shape 对象既不能安全地复制也不能按其编写方式分配。 【参考方案1】:

危险!!!

protected:
    int n = 2; //n denotes the number of dimensions
public:
    // default constructor
    Shape2D() :Shape(n)

初始化Shape(n)n未定义

同样的问题

Shape2D(const double side1, const double side2) :Shape(n)

如果可以,将n 定义为static const(或static constexpr,因为您标记了C++11)

 protected:
    static constexpr int n = 2; //n denotes the number of dimensions

否则,您应该定义一个静态的const/constexpr 变量(例如nDef),其值为2,并使用此常量初始化nShape()

无论如何,考虑一下,现在ShapeShape2D 的基类)被初始化之前 n 是该类的成员。

【讨论】:

【参考方案2】:

问题在于以下两行代码: int n = 2; //n denotes the number of dimensions Shape2D(const double side1, const double side2) :Shape(n) ...

问题是Shape()n 初始化之前被执行。详情请见constructors-called-before-initializing-variables。

解决此问题的方法是在 Shape 类中创建以下方法

protected: 
void InitializeBuffer(const int n)

sides = new double[n]
 

而不是在父构造函数中初始化sides,而是在Shape2D类的构造函数中调用这个InitializeBuffer

Shape2D(const double side1, const double side2) :Shape()

    InitializeBuffer (n);
    sides[0] = side1; sides[1] = side2;
 

【讨论】:

以上是关于CRT 检测到应用程序在堆缓冲区(新建/删除)类结束后写入内存的主要内容,如果未能解决你的问题,请参考以下文章

我该如何解决这个错误? CRT 检测到应用程序在堆缓冲区结束后写入内存

看似不错的删除 [] 程序崩溃

删除 3D 矩阵 c++

磁盘动态缓冲监视程序是个啥样的程序???

在 URL 上使用 Imagick 的 readImageFile 时如何修复“检测到无效的 CRT 参数”错误?

在运行时在堆上分配缓冲区