Home > Blockchain >  C program randomly stops
C program randomly stops

Time:01-29

  1. One time, my program runs and shows expected output, and sometime it don't (it compiles without any errors). Try-Catch doesen't seem to affect on this random output.

  2. v3f is a simple class that holds 3 floats: x,y,z and some basic math operations on them (all of them work perfectly fine)

v3f calculate_normal(v3f a, v3f b, v3f c);
  1. "calculate_normal" is just a simple multiplication and subtraction function that returns v3f, AND when it "decides" to work it gives expected output.
int main()
{
    lv::v3f c(-0.5, -0.5, 0);
    lv::v3f b(0, .5f, 0);
    lv::v3f a(0.5, -0.5, 0);
    /* if I add here 
          v3f d = a - b;
    */ it works !
    lv::v3f normal;

    std::cout << "1\n";
    normal = lv::calculate_normal(a, b, c);
    std::cout << "2\n";
    std::cout << normal.x << " " << normal.y << " " << normal.z << std::endl;
    std::cout << "3\n";

    return 0;
}

I cout'ed 1, 2 and 3 to see when program breaks and it's sometimes outputting all:

output:
1
2
0 0 1
3

And sometimes it stops on "1" (before calculating normal)

output:
1
// - - - - - - - - - - - - - - "Vector3.h"
#ifndef _LV_VECTOR_3_H_
#define _LV_VECTOR_3_H_

namespace lv{



template <class T>
class Vector3
{
    public:
        T x, y, z;

        Vector3(T _x = 0, T _y = 0, T _z = 0) : x(_x), y(_y), z(_z){}

        float length()
        {
            return sqrt( pow(x, 2)   pow(y, 2)   pow(z, 2) );
        }

        Vector3<T> normal()
        {
            float l = length();
            return Vector3<T>(x/l, y/l, z/l); 
        }

        void normalize()
        {
            float l = length();
            x /= l;
            y /= l;
            z /= l;
        }

        Vector3<T>& operator  = (const Vector3<T>& o)
        {
            this->x  = o.x;
            this->y  = o.y;
            this->z  = o.z;
            return *this;
        }

        Vector3<T>& operator -= (const Vector3<T>& o)
        {
            this->x -= o.x;
            this->y -= o.y;
            this->z -= o.z;
            return *this;
        }

        Vector3<T>& operator *= (const Vector3<T>& o)
        {
            this->x *= o.x;
            this->y *= o.y;
            this->z *= o.z;
            return *this;
        }
        
        Vector3<T>& operator /= (const Vector3<T>& o)
        {
            this->x /= o.x;
            this->y /= o.y;
            this->z /= o.z;
            return *this;
        }

        friend Vector3<T>& operator   (const Vector3<T>& o, const Vector3<T> p)
        {
            Vector3<T>* tmp;
            tmp->x = o.x   p.x;
            tmp->y = o.y   p.y;
            tmp->z = o.z   p.z;
            return *tmp;
        }

        friend Vector3<T>& operator - (const Vector3<T>& o, const Vector3<T> p)
        {
            Vector3<T>* tmp;
            tmp->x = o.x - p.x;
            tmp->y = o.y - p.y;
            tmp->z = o.z - p.z;
            return *tmp;
        }

        friend Vector3<T>& operator / (const Vector3<T>& o, const Vector3<T> p)
        {
            Vector3<T>* tmp;
            tmp->x = o.x / p.x;
            tmp->y = o.y / p.y;
            tmp->y = o.z / p.z;
            return *tmp;
        }

        friend Vector3<T>& operator * (const Vector3<T>& o, const Vector3<T> p)
        {
            Vector3<T>* tmp;
            tmp->x = o.x * p.x;
            tmp->y = o.y * p.y;
            tmp->z = o.z * p.z;
            return *tmp;
        }

        friend Vector3<T>& operator * (const Vector3<T>&o, float p)
        {
            Vector3<T>* tmp;
            tmp->x = o.x * p;
            tmp->y = o.y * p;
            tmp->z = o.z * p;
            return *tmp;
        }

        friend Vector3<T>& operator / (const Vector3<T>&o, float p)
        {
            Vector3<T>* tmp;
            tmp->x = o.x / p;
            tmp->y = o.y / p;
            tmp->z = o.z / p;
            return *tmp;
        }
};



#define v3f  Vector3<float>
#define v3i  Vector3<int>
#define v3d  Vector3<double>
#define v3ui Vector3<unsigned int>



}; // L V

#endif



//  - - - - - - - - - - - - - - "Vector.h"
#ifndef _LV_VECTOR_H_
#define _LV_VECTOR_H_

#include "Vector2.h"
#include "Vector3.h"
#include "Vector4.h"

#endif




//  - - - - - - - - - - - - - - "Utils.h"
#ifndef _LV_UTILS_H_
#define _LV_UTILS_H_

#include "Vector.h"

namespace lv {



v3f calculate_normal(v3f a, v3f b, v3f c)
{
    std::cout << "a\n";
    v3f u = b - a;
    v3f v = c - a;
    std::cout << "b\n";

    v3f n;
    n.x = u.y * v.z - u.z * v.y;
    n.y = u.z * v.x - u.x * v.z;
    n.z = u.x * v.y - u.y * v.x;
    std::cout << "c\n";

    return n;
}



}; // L V

#endif




// - - - - - - - - - - - - - - "main.cpp"
#include <iostream>
#include "Liviana/Math/Utils.h"

int main()
{

    lv::v3f c(-0.5, -0.5, 0);
    lv::v3f b(0, .5f, 0);
    lv::v3f a(0.5, -0.5, 0);
    lv::v3f normal;

    std::cout << "1\n";

    normal = lv::calculate_normal(a, b, c);
    
    std::cout << "2\n";
    std::cout << normal.x << " " << normal.y << " " << normal.z << std::endl;
    std::cout << "3\n";


    return 0;
}

CodePudding user response:

Only the mutating operators should return references. The other operators should return values.

OK:

Vector3<T>& operator  = (const Vector3<T>& o)

Not ok:

friend Vector3<T>& operator   (const Vector3<T>& o, const Vector3<T> p)

The above is not ok, because...what are you going to return a reference to? 1 2 is neither 1 nor 2. It's something else. You'll need storage for the result (a Vector3) and you'll need to return it by value.

friend Vector3<T> operator   (const Vector3<T>& o, const Vector3<T> p) {
    Vector3<T> tmp;
    tmp.x = o.x   p.x;
    tmp.y = o.y   p.y;
    tmp.z = o.z   p.z;
    return tmp;
}

Note the & is gone from the return type.

CodePudding user response:

You are dereferencing an uninitialized pointer in each of your arithmetic operators:

Vector3<T>& operator   (const Vector3<T>& o, const Vector3<T> p)
    Vector3<T>* tmp; // Where does tmp point to?
    tmp->x = o.x   p.x;
    tmp->y = o.y   p.y;
    tmp->z = o.z   p.z;
    return *tmp;
}

Dereferencing a pointer that doesn't point to a valid object within its lifetime is Undefined Behaviour, and causes your program to be invalid and able to do literally anything.

You should instead avoid using pointers. Just use an ordinary local variable and return it by value:

Vector3<T> operator   (const Vector3<T>& o, const Vector3<T> p)
    Vector3<T> tmp; // No more pointer
    tmp.x = o.x   p.x;
    tmp.y = o.y   p.y;
    tmp.z = o.z   p.z;
    return tmp;
}
  •  Tags:  
  • Related