Archived

This topic is now archived and is closed to further replies.

Kyo

vector1 = vector2 * 2.3 = debug assertion failed?

Recommended Posts

i''m testing my vector class and everything builds andcompiles but when i run it it says debug assertion failed. It only does this when i insert the line v1 = v2 * 3 which I overloaded with the following function:
  
inline CVector operator* (const CVector& vec,float s)
{
	return CVector(s*vec.v[0],s*vec.v[1],s*vec.v[2],s*vec.v[3]);
}
  
v1 = v2 works fine and so does v1 *= v2

Share this post


Link to post
Share on other sites
It seems like it does that debug assertion error only when i try to return a CVector into another CVector.


[edited by - Kyo on August 11, 2002 5:47:47 PM]

Share this post


Link to post
Share on other sites
Why not step into the code when it gives you the error and find the exact line it crashes on? And by that, I mean the exact line it executes before it gives you the error. That should give you what you need to know.

[ MSVC Fixes | STL | SDL | Game AI | Sockets | C++ Faq Lite | Boost | Asking Questions | Organising code files | My stuff ]

Share this post


Link to post
Share on other sites
I did i tried everything i could but i''m stumped. Here''s the class:


  
class CVector
{
public:
//constructors

CVector();
CVector(float a, float b, float c, float d);
~CVector();

//accessor functions

/*
const float& operator[] (int i) const { return v[i]; } //to read
float& operator() (int i) { return v[i]; } //to write
const float* ReadArray(void) { return v; }
float* GetArray(void) { return v; }*/


//private:

float v[3];

};



After creating the two CVectors


  
CVector vector2(0.4f,1.5f,-6.0f,1.0f);
CVector vector1(1.0f,1.0f,1.0f,1.0f);


I tested them the following way:

vector2 = vector1; <--works fine

vector1 = vector2 * 2; <--debug assertion error

vector1 * 3; <---same

vector2 *= 3; <--- works


I went through it line by line and it crashes when it tries to return a CVector in functions like these:


  
//--------------------------------------------------------

//vector times scalar (crashes after trying to return)

//--------------------------------------------------------

inline CVector operator* (const CVector& vec,float s)
{
return CVector(s*vec.v[0],s*vec.v[1],s*vec.v[2],s*vec.v[3]);
}



  
//--------------------------------------------------------

//reverse vector (crashes after trying to return

//--------------------------------------------------------

inline CVector operator- (const CVector& vec)
{
CVector tempvec(-vec.v[0],-vec.v[1],-vec.v[2],-vec.v[3]);
return tempvec;
}



  
//--------------------------------------------------------

//vector times equal scalar (works)

//--------------------------------------------------------

inline CVector& operator*= (CVector& vec,float s)
{
for (int i=0;i<4;i++)
{
vec.v[i] *= s;
}
return vec;
}


When it creates the vector using CVector(a,b,c,d) it goes through the constructor fine and gives the debug assertion error after it when it tries to return the vector. The constructor:


  
CVector::CVector(float a,float b,float c,float d)
{
v[0] = a;
v[1] = b;
v[2] = c;
v[3] = d;
}



I hope that''s enough information, it could be the operator overloading or use of consts as i''m not used to it fully yet.

Share this post


Link to post
Share on other sites
quote:
Original post by Kyo
float v[3];


You're declaring a 3-element array, but later you try to access v[3] (i.e. the 4th element). Change that declaration in the class to:

float v[4];


[edited by - Dactylos on August 11, 2002 8:09:55 PM]

Share this post


Link to post
Share on other sites
quote:
Original post by Dactylos
[quote]Original post by Kyo
float v[3];


You''re declaring a 3-element array, but later you try to access v[3] (i.e. the 4th element). Change that declaration in the class to:

float v[4];


[edited by - Dactylos on August 11, 2002 8:09:55 PM]

Nope still doesn''t work. Should''ve worked before too it went through the constructor giving v[3] a value without any problems.

Share this post


Link to post
Share on other sites
quote:
Original post by Kyo
Nope still doesn''t work. Should''ve worked before too it went through the constructor giving v[3] a value without any problems.

It doesn''t matter that it appeared to work, it was still wrong. It has to be v[4] if you want 4 elements.



[ MSVC Fixes | STL | SDL | Game AI | Sockets | C++ Faq Lite | Boost | Asking Questions | Organising code files | My stuff ]

Share this post


Link to post
Share on other sites
quote:
Original post by Kylotan
It doesn''t matter that it appeared to work, it was still wrong. It has to be v[4] if you want 4 elements.



ok but as i said still doesn''t work.

Share this post


Link to post
Share on other sites
I could not find any problems with your code, other than the array issue as stated above.

I created a CVector class based on your code and had no problems with it. I would like to see how you implement the CVector class in your code.

Share this post


Link to post
Share on other sites
Here''s the code in full.

CVector.h


  
#ifndef CVECTOR_H
#define CVECTOR_H

#include <math.h>
#include <windows.h>


class CVector
{
public:
//constructors

CVector();
CVector(float a, float b, float c, float d);
~CVector();

//accessor functions

/*
const float& operator[] (int i) const { return v[i]; } //to read
float& operator() (int i) { return v[i]; } //to write
const float* ReadArray(void) { return v; }
float* GetArray(void) { return v; }*/


//private:

float v[4];

};


//vector function declarations


extern inline CVector operator* (const CVector& vec, float s);
extern inline CVector operator* (float s, const CVector& vec);
extern inline CVector& operator*= (CVector& vec, float s);
extern inline CVector operator- (const CVector& vec);
extern inline CVector operator/ (const CVector& vec, float s);
extern inline CVector& operator/= (CVector& vec, float s);

extern inline CVector operator+ (const CVector& v1, const CVector& v2);
extern inline CVector& operator+ (CVector& v1, const CVector& v2);
extern inline CVector operator- (const CVector& v1, const CVector& v2);
extern inline CVector& operator- (CVector& v1, const CVector& v2);
extern inline bool operator== (const CVector& v1, const CVector& v2);

extern inline float dotProduct(const CVector& v1, const CVector& v2);
extern inline CVector crossProduct(const CVector& v1, const CVector& v2);

extern inline float lengthSquared(const CVector& vec);
extern inline float length(const CVector& vec);

extern inline CVector normalize(const CVector& vec);



#endif


CVector.cpp (only 3 operator overloads done)


  
//--------------------------------------------------------

//constructors and destructor

//--------------------------------------------------------

CVector::CVector()
{
memset(v,0,sizeof(float(3)));
}

CVector::CVector(float a,float b,float c,float d)
{
v[0] = a;
v[1] = b;
v[2] = c;
v[3] = d;
}

CVector::~CVector()
{
free(v);
}


//--------------------------------------------------------

//vector times scalar

//--------------------------------------------------------

inline CVector operator* (const CVector& vec,float s)
{
return CVector(s*vec.v[0],s*vec.v[1],s*vec.v[2],s*vec.v[3]);
}

//--------------------------------------------------------

//scalar times vector

//--------------------------------------------------------

inline CVector operator* (float s,const CVector& vec)
{
return vec * s;
}

//--------------------------------------------------------

//vector times equal scalar

//--------------------------------------------------------

inline CVector& operator*= (CVector& vec,float s)
{
for (int i=0;i<4;i++)
{
vec.v[i] *= s;
}
return vec;
}

//--------------------------------------------------------

//reverse vector

//--------------------------------------------------------

inline CVector operator- (const CVector& vec)
{
CVector tempvec(-vec.v[0],-vec.v[1],-vec.v[2],-vec.v[3]);
return tempvec;
}



Part of mainapp.cpp (init is called from winmain, CVector and other classes declared globally)


  
COpenGL ogl; //ogl object

CTexture texture; //texture object

CLight light; //lighting object

CVector vector2(0.4f,1.5f,-6.0f,1.0f);
CVector vector1(1.0f,1.0f,1.0f,1.0f);

bool Init()
{
//vector2 * 1; doesnt work

//-vector2; doesnt work

//vector1 = vector2 * 1; doesnt work

vector1 = vector2 //works

vector1 *= vector2 //works


if (!(texture.LoadBMP("Data\\treebark.bmp",1,true)))
{
return false;
}

light.EnableLight();
light.SetAmbient(1, 0.9f, 0.9f, 0.9f, 1.0f);
light.SetDiffuse(1, 1.0f, 1.0f, 1.0f, 1.0f);
light.SetPosition(1, 0.0f, 0.0f, 2.0f, 1.0f);
light.PointTo(1, -1.5f, 0.0f, -6.0f);
light.SwitchOn(1);

return true;
}



Share this post


Link to post
Share on other sites
OK.
The reason for the debug assertion is because you are creating a temporary vector, and then returning it. When the temporary goes out of scope, the destructor is called. This calls free. I don''t see any calls to malloc in the constructor, so that is the bug.

Also, in tbe constructor you are calling memset with the third argument float( 3 ) .
That doesn''t do what you are expecting it to do. sizeof( float ( 3) ) == sizeof (float). I think you want sizeof(float) * 3.

Share this post


Link to post
Share on other sites
Your error is being caused by the "free(v)" call in the CVector destructor.

Get rid of the memset call in the constructor and the free(v) call in the destructor and try it. It works fine for me.


Share this post


Link to post
Share on other sites
To "Paradigm Shifter": returning a temorary object is completly valid, since the object will be copied, but returning a reference wouldn''t.
And to Kyo: In VS, you can go to debug mode when the assertion dialog appers, then have a look at the call-stack. But I would agree with PigHeaded.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
When doing an = operator overloading you also need to define a copy constructor like this:



CVector::CVector(const CVector &p)
{
// Copy constructor
if(this == &p)
return;

for(int i=0;i<3;i++)
v = p.v[i];

}



Share this post


Link to post
Share on other sites
I didn''t say that it was a problem returning a tmporary, just that the temporary object is still constructed and destructed in the usual manner... I expect the original poster didn''t realise that if you return CVector(...) then the nameless CVector is still constructed and destructed.



Share this post


Link to post
Share on other sites