0xC0000005: Access violation reading location 0xCDCDCDC1

0

I wrote the code that can generate random Geometry figures and display it in cmd in text form.

Here is my 3 files:

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

Every 5-10 runs I got strange error:

Unhandled exception at 0x5214A9E8 (msvcr120d.dll) in Geometry.exe: 0xC0000005: Access violation reading location 0xCDCDCDC1.

Referring me to Destructor of Picture class. I can't reproduce this error and can't find the source of this error. Do you have any ideas how I can debug it?

c++
pointers
memory

3 Answers

0

If you want to debug the crash in C++ code, let me show you how to use and inspect dumps:

  1. Use adplus.exe (get it from Microsoft) and run your app in process monitor mode
  2. Download WinDBG (also from Microsoft)
  3. Use the following command to create a dump in monitor mode of your process

    ADPlus -Crash -pmn Geometry.exe -o C:\CrashDumps
    
  4. Open the crash dump in WinDBG
  5. Learn the power of WinDBG

A note: You might need symbols (.pdb) files to be created/loaded in your dump inspection

answered on Stack Overflow Aug 3, 2018 by Loop
0

The obvious error is that it is entirely (and easily) possible to attempt to delete an uninitialized m_shapes pointer in the Picture destructor.

The outline of your code is this:

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

In the ~Picture() function, you do the following:

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

In the Picture() constructor, you failed to initialize m_shapes, thus a simple one line program would be able to invoke the undefined behavior of calling delete on an uninitialized pointer.

Example:

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

Therefore the immediate fix is to go back and make sure m_shapes is initialized to (at least) a nullptr on construction of Picture.


However the ultimate fix is to start to use std::vector and other containers, in addition to using smart pointers such as std::shared_ptr<Shape> and/or std::unique_ptr<Shape>. When you do this, functions such as Picture::insert_shape become either obsolete, or are simple one-line functions issuing a call to (for example) std::vector<Shape*>::push_back().

For example (using a vector of raw pointers)

#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);
}
answered on Stack Overflow Aug 3, 2018 by PaulMcKenzie
0

The error is in this line.

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

You're not giving the size to your Picture pointer and you're deleting it like an array, You must assign a size to your pointer then you also can delete is like this.

delete [] main_pic;
answered on Stack Overflow Apr 6, 2020 by Sohail Iftikhar

User contributions licensed under CC BY-SA 3.0