mercredi 24 février 2016

Error: Invalid address specified to RtlValidateHeap - I can't figure out where I'm going wrong

I saw a couple answers about this error but they all involved a pointer being misused (void type being deleted, passing a deleted pointer, etc)

Here is the relevant code:

#pragma once
#include <wx/gdicmn.h>
#include <wx/pen.h>
#include <wx/brush.h>
#include <memory>

enum CommandType
{
    CM_DrawLine,
    CM_DrawEllipse,
    CM_DrawRect,
    CM_DrawPencil,
    CM_Move,
    CM_Delete,
    CM_SetPen,
    CM_SetBrush,
};

// Forward declarations
class PaintModel;
class Shape;

// Abstract Base Command class
// All actions that change the drawing (drawing, deleting, etc., are commands)
class Command
{
public:
    Command(const wxPoint& start, std::shared_ptr<Shape> shape);
    // Called when the command is still updating (such as in the process of drawing)
    virtual void Update(const wxPoint& newPoint);
    // Called when the command is completed
    virtual void Finalize(std::shared_ptr<PaintModel> &model) = 0;
    // Used to "undo" the command
    virtual void Undo(std::shared_ptr<PaintModel> &model) = 0;
    // Used to "redo" the command
    virtual void Redo(std::shared_ptr<PaintModel> &model) = 0;
    virtual ~Command() { }
protected:
    wxPoint mStartPoint;
    wxPoint mEndPoint;
    std::shared_ptr<Shape> mShape;
};

// Factory method to help create a particular command
struct CommandFactory
{
    static std::shared_ptr<Command> Create(std::shared_ptr<PaintModel> model,
        CommandType type, const wxPoint& start);
};

//DrawCommand class to implement drawings of each specific shape
class DrawCommand : public Command
{
public:
    DrawCommand(const wxPoint& start, std::shared_ptr<Shape> shape)
        :Command(start, shape) { };
    void Update(const wxPoint& newPoint) override;
    void Finalize(std::shared_ptr<PaintModel> &model) override;
    void Undo(std::shared_ptr<PaintModel> &model) override;
    void Redo(std::shared_ptr<PaintModel> &model) override;
};

And the relevant DrawCommand method, Undo:

void DrawCommand::Undo(std::shared_ptr<PaintModel> &model)
{
    model->RemoveShape(mShape);
}

Which calls the PaintModel method RemoveShape:

// Remove a shape from the paint model
void PaintModel::RemoveShape(std::shared_ptr<Shape> shape)
{
    auto iter = std::find(mShapes.begin(), mShapes.end(), shape);
    if (iter != mShapes.end())
    {
        mShapes.erase(iter);
    }
    return;
}

And here is the PaintModel header file:

#pragma once
#include <memory>
#include <vector>
#include "Shape.h"
#include "Command.h"
#include <wx/bitmap.h>
#include <stack>

class PaintModel : public std::enable_shared_from_this<PaintModel>
{
public:
    PaintModel();

    // Draws any shapes in the model to the provided DC (draw context)
    void DrawShapes(wxDC& dc, bool showSelection = true);

    // Clear the current paint model and start fresh
    void New();

    // Add a shape to the paint model
    void AddShape(std::shared_ptr<Shape> shape);

    // Remove a shape from the paint model
    void RemoveShape(std::shared_ptr<Shape> shape);

    //checks if there is a current active command
    bool HasActiveCommand();

    //Creates command given type and starting point
    void CreateCommand(CommandType &commType, wxPoint &start);

    //Updates endpoint to new point
    void UpdateCommand(wxPoint &point);

    //Calls finalize on current active command
    void FinalizeCommand();

    //sets current active command to new command
    void SetCurrActive(std::shared_ptr<Command> &active);

    //returns current active command
    std::shared_ptr<Command> GetCurrActive();

    //Adds a command to the undo stack
    void AddUndo(std::shared_ptr<Command> &lastCommand);

    //Adds a  command to the redo stack
    void AddRedo(std::shared_ptr<Command> &lastCommand);

    //Checks if undo is possible
    bool CanUndo();

    //Checks if redo is possible
    bool CanRedo();

    //undoes last action
    void Undo();

    //redoes previously undone action
    void Redo();

private:
    // Vector of all the shapes in the model
    std::vector<std::shared_ptr<Shape>> mShapes;

    //Current active command
    std::shared_ptr<Command> mCurrActive = nullptr;

    //undo/redo stacks
    std::stack<std::shared_ptr<Command>> mRedo;
    std::stack<std::shared_ptr<Command>> mUndo;

};

If it is not clear, what I am trying to do is remove the Shape pointer from the mShapes vector, which is a member of the PaintModel class. I followed everything and it works up to the end of RemoveShape, but breaks before exiting DrawCommand::Undo. I think, anyway, though I could be wrong. However when leaving RemoveShape, the mShapes vector exists and has the correct shape removed; however, once it goes back to the Undo method mShapes appears to be empty.

Aucun commentaire:

Enregistrer un commentaire