Ошибка повреждения кучи, связанная с приведением - PullRequest
0 голосов
/ 28 мая 2018

Я получаю следующую ошибку

"ОБНАРУЖЕНА КОРРУПЦИЯ КАРТЫ: после блока Normal (# 271) в 0x0108C4A8. CRT обнаружил, что приложение записало в память после завершения буфера кучи."

Справочная информация

Я пытаюсь эмулировать наследование, полиморфизм и динамическое связывание методов в c ++ без фактического использования этих функций.У меня есть функция, которая эмулирует конструктор с именем Square_new (x, y, sidelen), который вызывает new и возвращает указатель Square.Затем я приведу это к родительскому классу "Shape".Я знаю, что этот код работает

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;

Однако, когда я добавляю следующий код (конечно, над вызовом удаления)

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

Вот реализация 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;
}

Квадрат в свою очередь «получен» из прямоугольника, который получен из 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;


}

Вот родительский элемент прямоугольника

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

1 Ответ

0 голосов
/ 28 мая 2018

Оказалось, очень непонятная ошибка.Предполагается, что структуры используются для представления классов.Когда Square создается, он вызывает конструктор прямоугольника.Однако для того, чтобы это работало, квадрат должен иметь те же поля, что и прямоугольник.Я не опубликовал это в коде, так что никто не смог бы мне помочь (извините, что потратил ваше время), но в любом случае здесь он теперь

Изначально внутри Square.h и 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;
};

Когда Квадрат должен был быть определен следующим образом

struct Square {
    void** vmt;

    //shape
    double positionX;
    double positionY;

    //rectangle
    double width;
    double height;
};

Я до сих пор не понимаю, почему это даже имеет значение, поэтому, если кто-то захочет прийти к объяснению и объяснить, мне будет интересно узнать

...