0xC0000005:访问冲突读取位置0xCDCDCDC1

时间:2018-08-03 11:25:05

标签: c++ pointers memory

我编写了可以生成随机几何图形并以cmd形式以文本形式显示的代码。

这是我的3个文件:

Geometry.h

#pragma once

#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
#define new DEBUG_NEW


#include <iostream>
#include <time.h>
#include <fstream>
#include <string>

#define PI 3.1415926535
using namespace std;

enum color { White, Red, Green, Blue, Yellow, Black };
enum _shape { line, rectangle, circle, picture }; //to roll shapes

void print_color(color c);

//--------------------------Point---------------------------
class Point {
private:
    int m_xc, m_yc; //(x,y) coordinats
public:
    Point(int x = 0, int y = 0) : m_xc(x), m_yc(y) {}
    int x(void) const   { return m_xc; };
    int y(void) const   { return m_yc; };
    Point operator+(const Point& p) const 
    {
        return Point(m_xc+p.m_xc, m_yc+p.m_yc);
    }
    Point& operator+=(const Point& p) //move point
    { 
        m_xc += p.m_xc; 
        m_yc += p.m_yc; 
        return *this; 
    } 
    friend ostream& operator<<(ostream& os, const Point& p);
    Point move(int x, int y){
        m_xc += x;
        m_yc += y;
        return *this;
    }
};

//------------------------Shape-----------------------------

class Shape  {
protected:
    Point m_org; 
    color m_color; 
    _shape m_shape;
public:
    Shape(const Point& p1 = 0, color c = White, _shape sh = line) : m_org(p1), m_color(c), m_shape(sh){};
    virtual ~Shape() = 0 {};
    virtual void move(const Point& p) = 0;
    virtual void draw(char tabs) const = 0;
    virtual void Who_am_I() const = 0;
    virtual double Area() const { return 0; };
    virtual void Save2File(ofstream &myfile) const = 0;
};
//------------------------Line---------------------------------

class Line : public Shape {
protected:
    Point m_end; // line end
public:
    Line(const Point& p1, const Point& p2, color c) : Shape(p1, c, line), m_end(p2) {}
    void move(const Point& p)
    {
        m_org += p;
        m_end += p;
    }
    void draw(char tabs) const;
    void Who_am_I() const { 
        print_color(m_color);
        cout << "Line"; 
    }
    double length() const;
    double Area() const { return 0; };
    void Save2File(ofstream &myfile) const;
};
//----------------------Rectangle-------------------------------

class Rectangle : public Shape {
protected:
    int width;
    int height;
public:
    Rectangle(const Point& p1, color c = White, int w = 0, int h = 0) : Shape(p1, c, rectangle), width(w), height(h) {}
    void move(const Point& p)
    {
        m_org += p;
    }
    void draw(char tabs) const;
    void Who_am_I() const { 
        print_color(m_color);
        cout << "Rectangle"; 
    }
    double Area() const { return width*height; };
    void Save2File(ofstream &myfile) const;
};
//----------------------Circle---------------------------

class Circle : public Shape {
protected:
    int radius;
public:
    Circle(const Point& p1, color c = White, int r = 0) : Shape(p1, c, circle), radius(r) {};
    void move(const Point& p)
    {
        m_org += p;
    }
    void draw(char tabs) const;
    void Who_am_I() const { 
        print_color(m_color);
        cout << "Circle"; 
    }
    double Area() const { return PI*(double)radius*(double)radius; };
    void Save2File(ofstream &myfile) const;
};
//--------------------------Picture-------------------------

class Picture : public Shape {
private:
    Picture(const Picture&); //CCtor is not accessible from main
protected:
    Shape** m_shapes;   //array of pointers to shapes
    int m_count;        //number of shapes
    static unsigned idx; //number of pictures created for debug
public:
    Picture(const Point& p1 = 0, color c = White) : Shape(p1, c, picture), m_count(0){ idx++; }
    ~Picture();
    void insert_shape(Shape* sh);
    void draw(char tabs) const;
    void move(const Point& p){ m_org += p; };
    void Who_am_I() const { 
        print_color(m_color);
        cout << "Picture"; 
    }
    void Save2File(ofstream &myfile) const;
    int get_count(void){ return m_count; }
    double Area() const;
    unsigned GetAmPic(void) { return idx; }
};

Geometry.cpp

#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
#define new DEBUG_NEW

#include "geometry.h"
using namespace std;

unsigned Picture::idx = 0;

ostream& operator<<(ostream& os, const Point& p)
{
    os << '(' << p.x() << ',' << p.y() << ')';
    return os;
}

void print_color(color c) {
    string color_print[6] = { "White ", "Red ", "Green ", "Blue ", "Yellow ", "Black " };
    cout << color_print[(int)c];
}

//------------------Line methods--------------------
void Line::draw(char tabs) const
{
    cout << string(tabs, '\t');
    Who_am_I();
    cout << " from " << m_org << " to " << m_end << endl;
}

double Line::length() const
{
    return sqrt((double)((m_org.x()-m_end.x())*(m_org.x()-m_end.x()) + (m_org.y()-m_end.y())*(m_org.y()-m_end.y())));
}

void Line::Save2File(ofstream& myfile) const {// save to file
    myfile << 'L' << " " << m_color << " " << m_org.x() << " " << m_org.y() << " "
        << m_end.x() << " " << m_end.y() << endl;
}

//------------------Rectangle methods----------------
void Rectangle::draw(char tabs) const
{
    cout << string(tabs, '\t');
    Point temp1 = m_org;
    Point temp2 = m_org;
    Line l1(temp1, temp2.move(width, 0), m_color);
    temp1 = temp2;
    Line l2(temp2, temp1.move(0, height), m_color);
    temp2 = temp1;
    Line l3(temp1, temp2.move(-width, 0), m_color);
    temp1 = temp2;
    Line l4(temp2, temp1.move(0, -height), m_color);
    Who_am_I(); cout << endl;
    cout << string(tabs, '\t'); l1.draw(1);
    cout << string(tabs, '\t'); l2.draw(1);
    cout << string(tabs, '\t'); l3.draw(1);
    cout << string(tabs, '\t'); l4.draw(1);
}

void Rectangle::Save2File(ofstream& myfile) const {// save to file
    myfile << 'R' << " " << m_color << " " << m_org.x() << " " << m_org.y() << " " << width
        << " " << height << endl;
}

//----------------------Circle methods---------------------------
void Circle::draw(char tabs) const
{
    cout << string(tabs, '\t');
    Who_am_I();
    cout << " Center in " << m_org << " Radius is " << radius << endl;
}

void Circle::Save2File(ofstream& myfile) const {// save to file
    myfile << 'C' << " " << m_color << " " << m_org.x() << " " << m_org.y() << " "
        << radius << endl;
}


//----------------------Picture methods--------------------------
void Picture::insert_shape(Shape* s) // insert a new shape to picture
{
    if (m_count == 0)  {//new picture creating
        m_shapes = new Shape*[1];
        if (!m_shapes)
            cout << "Can't allocate memory!";
    }
    if (m_count > 0){
        Shape** temp = new Shape*[m_count];
        memcpy(temp, m_shapes, sizeof(Shape*)*m_count); //save to temp
        delete m_shapes; //delete old array
        m_shapes = new Shape*[m_count + 1];  //add 1 more place
        if (!m_shapes)
            cout << "Can't allocate memory!";
        memcpy(m_shapes, temp, sizeof(Shape*)*m_count); //return to array
        delete temp; 
    }
    m_shapes[m_count] = s;  // insert the new shape into the last slot in the array
    m_shapes[m_count]->move(m_org); //adjusts the location of the shape
    m_count++;      // increment the number of shapes in picture
}



void Picture::draw(char tabs) const
{
    cout << string(tabs, '\t');
    cout << "------------------ "; 
    Who_am_I();
    cout << " ----------------------" << endl;
    for (unsigned i = 0; i < m_count; i++)
    {
        m_shapes[i]->draw(tabs + 1);    // draw each shape
    }
    cout << string(tabs, '\t');
    cout << "------------------ End ";
    Who_am_I();
    cout << " ------------------ " << endl;
}

double Picture::Area() const //sum of areas of all shapes in the picture
{
    double area = 0;
    for (int i = 0; i < m_count; i++)
    {
        area += m_shapes[i]->Area();
    }
    return area;
}


Picture::~Picture()
{
    for (int i = 0; i < m_count; i++){
        if (m_shapes[i])
            delete m_shapes[i];
    }
    Who_am_I(); cout << " deleting..." << endl;
    // sometimes (every 5-10 runs) error here. can't reproduce and debug
    if (m_shapes)
        delete m_shapes; 
    // seems like program try to delete already freed memory
}

void Picture::Save2File(ofstream& myfile) const // save to file
{
    myfile << 'P' << " " << m_color << " " << m_org.x() << " " << m_org.y() << endl;
    for (int i = 0; i < m_count; i++)
        m_shapes[i]->Save2File(myfile);
    myfile << 'E' << endl; // end of a picture
}

drawing_app.cpp

#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
#define new DEBUG_NEW

#include "geometry.h"
#include <iostream>
#define MAX_PICS_IN_PIC 3
#define MAX_SHAPES 5
using namespace std;

void randomizer(Picture*, int); //recursive function
Picture* Load(istream&);
Point GenP(void);
color GenC(void);
int GenLen(void);

int main(void)
{
    srand((unsigned int)time(NULL));

    Picture *main_pic = new Picture(Point(0, 0), GenC());
    ofstream myfile_write("myfile.txt", ios::out);
    if (!myfile_write.is_open())
        cout << "Can't open file!" << endl;
    randomizer(main_pic, MAX_PICS_IN_PIC); //recursive function
    main_pic->Save2File(myfile_write); //save picture to file
    myfile_write.close();
    cout << "       Created Picture:" << endl << endl;
    main_pic->draw(0); //draw the main picture
    cout << "Created: " << main_pic->GetAmPic() << " pictures." << endl; // for debugging
    delete[] main_pic;

    ifstream myfile_read("myfile.txt", ios::in);
    if (!myfile_read.is_open())
        cout << "Can't open file!" << endl;
    Picture* buff_pic = Load(myfile_read);  //load the picture from the file
    cout << endl << endl << "       Loaded Picture:" << endl << endl;
    buff_pic->draw(0);  //display loaded picture
    myfile_read.close();
    delete[] buff_pic;

    cout << "\nLeaks: " << _CrtDumpMemoryLeaks() << endl;
    return 0;
}

void randomizer(Picture* pic, int count) {
    for (int i = 0; i < MAX_SHAPES; i++){
        Point p1 = GenP(); //m_org of the shape
        color c = GenC(); //roll random color
        _shape shape;
        shape = (_shape)(rand() % 4); //roll random shape
        if (shape == line){
            Point p2 = GenP();
            Line* _line = new Line(p1, p2, c);
            pic->insert_shape(_line);
        }
        if (shape == rectangle){
            Rectangle* _rect = new Rectangle(p1, c, GenLen(), GenLen());
            pic->insert_shape(_rect);
        }
        if (shape == circle){
            Circle* _circ = new Circle(p1, c, GenLen());
            pic->insert_shape(_circ);
        }
        if (shape == picture){
            if (count > 0){
                Picture* inner_pic = new Picture(p1, c);
                count--;
                randomizer(inner_pic, count);
                pic->insert_shape(inner_pic);
            }
            else return;
        }
    }
}

Picture* Load(istream& myfile) {
    int m_color, m_org_x, m_org_y;
    char m_shape;
    myfile >> m_shape >> m_color >> m_org_x >> m_org_y; //read first line
    Picture* pic = new Picture(Point(m_org_x, m_org_y), (color)m_color); //create the main picture
    myfile >> m_shape; //read next line for shape
    while (m_shape != 'E')
    {
        if (m_shape == 'L'){
            int m_end_x, m_end_y;
            myfile >> m_color >> m_org_x >> m_org_y >> m_end_x >> m_end_y;
            Line* _line = new Line(Point(m_org_x, m_org_y), Point(m_end_x, m_end_y), (color)m_color);
            pic->insert_shape(_line);
        }
        if (m_shape == 'C'){
            int radius;
            myfile >> m_color >> m_org_x >> m_org_y >> radius;
            Circle* Circel = new Circle(Point(m_org_x, m_org_y), (color)m_color, radius);
            pic->insert_shape(Circel);
        }
        if (m_shape == 'R') {
            int m_width, m_height;
            myfile >> m_color >> m_org_x >> m_org_y >> m_width >> m_height;
            Rectangle* Rect = new Rectangle(Point(m_org_x, m_org_y), (color)m_color,
                m_width, m_height);
            pic->insert_shape(Rect);
        }
        if (m_shape == 'P') {
            myfile.seekg(-1, ios::cur);
            Picture* inner_pic = Load(myfile);
            pic->insert_shape(inner_pic);
        }
        myfile >> m_shape;
    }
    return pic;
}

Point GenP(){ //roll random point x = 0 to 30, y = 0 to 30
    Point p(rand() % 31, rand() % 31);
    return p;
}

color GenC(){ //generate random color
    return (color)(rand() % 6);
}

int GenLen(){ // generate random length from 1 to 50
    return rand() % 50 + 1;
}

每5到10次运行,我都会收到一个奇怪的错误:

  

Geometry.exe中0x5214A9E8(msvcr120d.dll)的未处理异常:0xC0000005:访问冲突读取位置0xCDCDCDC1。

将我引荐到Picture类的析构函数。我无法重现此错误,也找不到此错误的来源。您有什么想法可以调试吗?

3 个答案:

答案 0 :(得分:0)

如果您想用C ++代码调试崩溃,请让我向您展示如何使用和检查转储:

  1. 使用adplus.exe(从Microsoft获得)并在进程监控器模式下运行您的应用
  2. 下载WinDBG(同样从Microsoft)
  3. 使用以下命令在进程的监视方式下创建转储

    ADPlus -Crash -pmn Geometry.exe -o C:\CrashDumps
    
  4. 在WinDBG中打开故障转储
  5. 了解WinDBG的功能

注意:您可能需要在转储检查中创建/加载符号(.pdb)文件

答案 1 :(得分:0)

一个明显的错误是,完全有可能(而且很容易)尝试在delete析构函数中m_shapes一个未初始化的Picture指针。

您的代码概述如下:

class Picture : public Shape {
private:
    Picture(const Picture&); //CCtor is not accessible from main
protected:
    Shape** m_shapes;   //array of pointers to shapes
    int m_count;        //number of shapes
    static unsigned idx; //number of pictures created for debug
public:
    Picture(const Point& p1 = 0, color c = White) : Shape(p1, c, picture), m_count(0){ idx++; }
    //...
    ~Picture();
};

~Picture()函数中,您可以执行以下操作:

Picture::~Picture()
{
    for (int i = 0; i < m_count; i++){
        if (m_shapes[i])
            delete m_shapes[i];
    }

    if (m_shapes)  // This may not have been initialized!!
        delete m_shapes; 
}

Picture()构造函数中,您未能初始化m_shapes,因此,一个简单的单行程序将能够调用未初始化指针上的调用delete的未定义行为。

示例:

int main() 
{
    Picture p(Picture(Point(0, 0), GenC()));
} // The `p` destructor will invoke undefined behavior.

因此,立即修复是返回并确保在构造m_shapes时将nullptr初始化为(至少)Picture


但是,最终的解决方法是除了使用std::vector和/或std::shared_ptr<Shape>等智能指针之外,还开始使用std::unique_ptr<Shape>和其他容器。执行此操作时,诸如Picture::insert_shape之类的函数要么过时,要么是简单的单行函数,发出对std::vector<Shape*>::push_back()的调用。

例如(使用原始指针向量)

#include <vector>
class Picture
{
    //...
    std::vector<Shape *> m_shapes;
    void insert_shape(Shape* s);
   //...
};

void Picture::insert_shape(Shape* s) 
{
   m_shapes.push_back(s);
}

答案 2 :(得分:0)

此行中有错误。

Picture *main_pic = new Picture(Point(0, 0), GenC());

您没有给图片指针指定大小,而是像数组一样将其删除。您必须为指针分配大小,然后也可以像这样删除。

delete [] main_pic;