0

I have two classes Mat3 and Vec3, placed in separate files. Mat3 is composed of array of Vec3, and Vec3 uses Mat3 in some of calculations, so those files include each other. I have placed prototypes of them in headers, but in Mat3 it's problematic. Array of Vec3 does not compile due to incomplete type, so I changed it to Vec3* and planned to allocate memory in constructor, but there is assertion fail when using new or malloc (I know, that new uses malloc, just pointing out combinations I used) that goes:

Mapper: malloc.c:2379: sysmalloc: Assertion `(old_top == initial_top (av) && old_size == 0) || ((unsigned long) (old_size) >= MINSIZE && prev_inuse (old_top) && ((unsigned long) old_end & (pagesize - 1)) == 0)' failed.

So now I have no idea how to manage all of these. Can you help?

I'm placing simplified classes below, for better understanding:

---------Vec3.h-----------
#ifndef VEC3_H
#define VEC3_H
#include <cmath>
#include <assert.h>
#include "Vec2.h"
#include "Mat3.h"
namespace API
{
    namespace Data
    {
        struct Mat3;
        struct Vec3
        {
            float X = 0.0f;
            float Y = 0.0f;
            float Z = 0.0f;
            Vec3();
            Vec3(float, float, float);
            Vec3(Vec3*);
            void Rotate(const Vec3);
        };
    }
}
#endif

---------Vec3.cpp-----------
#include "Vec3.h"

API::Data::Vec3::Vec3()
{
}

API::Data::Vec3::Vec3(float x, float y, float z)
{
    X = x;
    Y = y;
    Z = z;
}

API::Data::Vec3::Vec3(Vec3* original) : API::Data::Vec3::Vec3(original->X, original->Y, original->Z)
{
}

void API::Data::Vec3::Rotate(const API::Data::Vec3 angles)
{
    Mat3 rotationMatrix = Mat3(0.0f);
    Mat3 xRotation = Mat3(0.0f);
    Mat3 yRotation = Mat3(0.0f);
    Mat3 zRotation = Mat3(0.0f);
    xRotation.XRotation(angles.X);
    ///
    yRotation.YRotation(angles.Y);
    ///
    zRotation.ZRotation(angles.Z);

    rotationMatrix = xRotation * yRotation * zRotation;
    Vec3 effect = rotationMatrix * (*this);
    X = effect.X;
    Y = effect.Y;
    Z = effect.Z;
}
-------Mat3.h------------
#ifndef MAT3_H
#define MAT3_H
#include <vector>
#include <assert.h>
#include "Vec3.h"
namespace API
{
    namespace Data
    {
        struct Vec3;
        struct Mat3
        {
        private:
            Vec3* _columns = nullptr;
        public:
            Mat3();
            Mat3(const Mat3&);
            Mat3(float);
        };
    }
}
#endif // !MAT3_H

-------Mat3.cpp-------
API::Data::Mat3::Mat3(float value)
{
    _columns = new API::Data::Vec3[3]; // Assertion fail fires here
    //OR
    // _columns = (API::Data::Vec3*)malloc(3 * sizeof(API::Data::Vec3));
    for (int i = 0; i < 3; i++)
    {
        _columns[i] = API::Data::Vec3();
        for (int j = 0; j < 3; j++)
        {
            _columns[i][j] = value;
        }
    }
}

API::Data::Mat3::Mat3() : API::Data::Mat3(0.0f)
{
}

API::Data::Mat3::Mat3(const API::Data::Mat3& original) : API::Data::Mat3(0.0f)
{
    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            _columns[i][j]= original[i][j];
        }
    }
}

EDIT: Code has been updated to minimal compilable version.

Adam Kaczmarski
  • 338
  • 1
  • 12

1 Answers1

1

This works for me :

Vec3.h

#ifndef VEC3_H
#define VEC3_H
#include <cmath>
#include <assert.h>
namespace API
{
    namespace Data
    {
        struct Mat3;//forward declaration
        struct Vec3
        {
            float X = 0.0f;
            float Y = 0.0f;
            float Z = 0.0f;
            Vec3();
            Vec3(float, float, float);
            Vec3(Vec3*);
            void Rotate(const Vec3);
        };
    }
}
#endif

Vec3.cpp

#include "Vec3.h"
#include "Mat3.h"

API::Data::Vec3::Vec3()
{
}

API::Data::Vec3::Vec3(float x, float y, float z)
{
    X = x;
    Y = y;
    Z = z;
}

API::Data::Vec3::Vec3(Vec3* original) : API::Data::Vec3::Vec3(original->X, original->Y, original->Z)
{
}

void API::Data::Vec3::Rotate(const API::Data::Vec3 angles)
{
    Mat3 rotationMatrix = Mat3(0.0f);
    Mat3 xRotation = Mat3(0.0f);
    Mat3 yRotation = Mat3(0.0f);
    Mat3 zRotation = Mat3(0.0f);
    //Comments because you have not implemented rotations for instance
    /*xRotation.XRotation(angles.X);
    ///
    yRotation.YRotation(angles.Y);
    ///
    zRotation.ZRotation(angles.Z);

    rotationMatrix = xRotation * yRotation * zRotation;
    Vec3 effect = rotationMatrix * (*this);
    X = effect.X;
    Y = effect.Y;
    Z = effect.Z;*/
}

Mat3.h

#ifndef MAT3_H
#define MAT3_H
#include <assert.h>
namespace API
{
    namespace Data
    {
        struct Vec3;//forward declaration
        struct Mat3
        {
        private:
            Vec3* _columns = nullptr;
        public:
            Mat3();
            Mat3(const Mat3&);
            Mat3(float);
            ~Mat3();
        };
    }
}
#endif // !MAT3_H

Mat3.cpp

#include "Mat3.h"
#include "Vec3.h"


API::Data::Mat3::Mat3(float value)
{
    _columns = new API::Data::Vec3[3];
    assert(_columns != 0);

    for (int i = 0; i < 3; i++)
    {
        _columns[i] = API::Data::Vec3();
        _columns[i].X = value;
        _columns[i].Y = value;
        _columns[i].Z = value;
    }
}

API::Data::Mat3::Mat3() : API::Data::Mat3(0.0f)
{
}

API::Data::Mat3::Mat3(const API::Data::Mat3& original) : API::Data::Mat3(0.0f)
{
    for (int i = 0; i < 3; i++)
    {

        _columns[i].X = original._columns[i].X;
        _columns[i].Y = original._columns[i].Y;
        _columns[i].Z = original._columns[i].Z;
    }
}


API::Data::Mat3::~Mat3() {
    delete[] _columns;
}

In C/C++, when you play with the "cross reference" system, you always put a forward declaration of your class in headers and it's useless to include headers of this class. circular dependency-wiki. So, in ".cpp" files, you should include your headers to have the definitions of your class (and not only the declaration).

One other thing : if you allocate data on the heap (with new[]) in the constructor, you should remove this in the destructor (with delete[]).

Gentil-N
  • 124
  • 1