Drawkcab Esrever
Drawkcab Esrever

Reputation: 141

Heap Corruption Error Related to Casting

I am getting the following error

"HEAP CORRUPTION DETECTED: after Normal block (#271) at 0x0108C4A8. CRT detected that the application wrote to memory after end of heap buffer."

Background info

I am attempting to emulate inheritance,polymorphism, and dynamic method binding in c++ without actually using these features. I have a function thats emulating a constructor called 'Square_new(x,y,sidelen)' that calls new and returns a Square pointer. I then cast this to the parent class "Shape". I know that this code works

cout << "TESTING SQUARE" << endl;
cout << "Initializing Square at x=1,y=1,sidelength=5" << endl;
Shape* s2 = (Shape*)Square_new(1, 1, 5);
cout << "Expected area = 5*5 = 25" << endl << endl;

// later on in the code
delete s2;

However when I add the following code (above the delete invocation of course)

//Added Portion
Rectangle* r2 = (Rectangle*)s2;
Square* sq = (Square*)s2;

Here is the implementation of Square.cpp

    void** vmtSquare;

Square* Square_new(double positionX, double positionY, double sidelength) {
    Square* s = new Square;
    Square_Square(s, positionX, positionY, sidelength);
    s->vmt = vmtSquare;
    return s;
}
void Square_Square(Square* _this, double positionX, double positionY, double sidelength) {
    Rectange_Rectangle((Rectangle*)_this, positionX, positionY, sidelength, sidelength);
    Square_createVMT;
}

// This resize will ovveride the rectangle resize
void Square_resizeA(Rectangle* _this, double width, double height) {
    if (width == height) {
        Rectangle_resize(_this, width, height);
    }
}

// following two functions are extensions
void Square_resizeB(Square* _this, double sidelength) {
    Rectangle_resize((Rectangle*)_this, sidelength, sidelength);
}

double Square_getSideLength(Square* _this) {
    return Rectangle_getWidth((Rectangle*)_this);

}

void Square_Destructor(Square* _this) {
    // The function doesnt do any thing but call
    // parent destructor (Rectangle)
    Rectangle_Destructor((Rectangle*)_this);
}

void Square_createVMT() {
    // copy Rectangle vmt
    vmtSquare = new void*[10];
    vmtSquare[0] = (void*)Shape_getPositionX;
    vmtSquare[1] = (void*)Shape_getPositionY;
    vmtSquare[2] = (void*)Shape_move;
    vmtSquare[3] = (void*)Rectangle_area;
    vmtSquare[4] = (void*)Rectangle_Destructor;
    vmtSquare[5] = (void*)Rectangle_getWidth;
    vmtSquare[6] = (void*)Rectangle_getHeight;
    //override rectangle resize and destructor
    vmtSquare[4] = (void*)Square_Destructor;
    vmtSquare[7] = (void*)Square_resizeA;
    //extension methods
    vmtSquare[8] = (void*)Square_resizeB;
    vmtSquare[9] = (void*)Square_getSideLength;
}

Square in turn is 'derived' from rectangle, which is derived from Shape

// Rectangle.cpp
// Assignment 4 example

#include "Rectangle.h"
#include "Shape.h"

void** vmtRectangle;

Rectangle* Rectangle_new(double positionX, double positionY, double width, double height) {
    Rectangle* r = new Rectangle;
    Rectange_Rectangle(r, positionX, positionY, width, height);
    r->vmt = vmtRectangle;
    return r;
}

void Rectange_Rectangle(Rectangle* _this, double positionX, double positionY, double width, double height) {
    //set fields for this Rectangle
    _this->width = width;
    _this->height = height;
    Shape_Shape((Shape*)_this, positionX, positionY);
    Rectangle_createVMT();

}

double Rectangle_getWidth(Rectangle*_this) {
    return _this->width;
}

double Rectangle_getHeight(Rectangle* _this) {
    return _this->height;
}
void Rectangle_resize(Rectangle* _this, double width, double height) {
    _this->width = width;
    _this->height = height;
}

double Rectangle_area(Shape* _this) {
    Rectangle* r = (Rectangle*)_this;
    return r->height * r->width;
}

void Rectangle_Destructor(Rectangle* _this) {
    //doesnt do anything accept call parent's destructor
    Shape_Destructor((Shape*)_this);
}

void Rectangle_createVMT() {
    vmtRectangle = new void*[8];

    //copy shapes vmt
    vmtRectangle[0] = (void*)Shape_getPositionX;
    vmtRectangle[1] = (void*)Shape_getPositionY;
    vmtRectangle[2] = (void*)Shape_move;
    vmtRectangle[3] = (void*)0;
    vmtRectangle[4] = (void*)Shape_Destructor;

    //overwrite area and destructor
    vmtRectangle[3] = (void*)Rectangle_area;
    vmtRectangle[4] = (void*)Rectangle_Destructor;

    //extensions
    vmtRectangle[5] = (void*)Rectangle_getWidth;
    vmtRectangle[6] = (void*)Rectangle_getHeight;
    vmtRectangle[7] = (void*)Rectangle_resize;


}

Here is Parent of Rectangle

// Shape.cpp
// Assignment 4 example
// Contains the definitions needed to emulate the Shape "class".

#include "Shape.h"

void Shape_Shape(Shape* _this, double positionX, double positionY)
{
    _this->positionX = positionX;
    _this->positionY = positionY;
}

double Shape_getPositionX(Shape* _this)
{
    return _this->positionX;
}

double Shape_getPositionY(Shape* _this)
{
    return _this->positionY;
}

void Shape_move(Shape* _this, double positionX, double positionY)
{
    _this->positionX = positionX;
    _this->positionY = positionY;
}


void Shape_Destructor(Shape* _this) {
    //this function does absolutely nothing
    //and is here for emulation purposes
}

void Shape_createVMT()
{
    vmtShape = new void*[5];
    vmtShape[0] = (void*) Shape_getPositionX;
    vmtShape[1] = (void*) Shape_getPositionY;
    vmtShape[2] = (void*) Shape_move;

    // area() is abstract, so its entry in the VMT should be 0 (NULL).
    vmtShape[3] = (void*) 0;
    vmtShape[4] = Shape_Destructor;
}

Upvotes: 0

Views: 296

Answers (1)

Drawkcab Esrever
Drawkcab Esrever

Reputation: 141

It turned out to be a super obscure error. The structs are supposed are used to represent classes. When Square is constructed it calls the rectangle constructor. However In order for this to work square must have the exact same fields as rectangle. I didn't post this in the code so there is no way anyone could have helped me (sorry for wasting your time) but anyway here it is now

Originally inside of Square.h and Rectangle.h

struct Square {
    void** vmt;

    //shape
    double positionX;
    double positionY;
};



struct Rectangle {
    void** vmt;

    //shape
    double positionX;
    double positionY;

    //rectangle
    double width;
    double height;
};

When Square should have been defined as follows

struct Square {
    void** vmt;

    //shape
    double positionX;
    double positionY;

    //rectangle
    double width;
    double height;
};

I still have no idea why this even matters so if anyone wants to commnent and explain I would be interested to know

Upvotes: 1

Related Questions