1

I an trying to write c++ code using openGl to render Sierpinski_gasket. I have defined tow new data types using typedef, and then i create a pointer to one of those new datatypes:

typedef GLfloat point2[2]; 
typedef point2 myTriangle[3];
myTriangle *triangle;

I write a function init that takes three points, then create a new myTriangle and then assign it to *triangle

void init(point2 p1, point2 p2, point2 p3){  
    myTriangle t;
    t[0][0] = p1[0];
    t[0][1] = p1[1];

    t[1][0] = p2[0];
    t[1][1] = p2[1];

    t[2][0] = p3[0];
    t[2][1] = p3[1];

    triangle = &t;    
}

this is my diplay function:

void display(void){
    static point2 p = {1,1};
    int i;        
    //pick a random vertex    
    i = rand() % 3;  //i in the range 0 to 2

    p[0] = (p[0] + *triangle[i][0])/2;
    p[1] = (p[1] + *triangle[i][1])/2;
    cout << p[0] << ' , ' << p[1] << endl;
    //display new points
    glBegin(GL_POINTS);
        glVertex2fv(p);
    glEnd();                
}

the problem is that the values of *triangle changes after each call to display.. Can anyone tell me why and how to fix that ?

the full code is below

#include <GL/glew.h>
#include <GL/freeglut.h>
#include <cstdlib>
#include <iostream>
using namespace std;

typedef GLfloat point2[2];
typedef point2 myTriangle[3];

myTriangle *triangle;
void init(point2 p1, point2 p2, point2 p3);
void display(void);
int main(int argc, char** argv) {
    //initialize the GLUT library
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE);
    glutInitWindowSize(500, 500);
    glutInitWindowPosition(100, 100);
    glutCreateWindow("OpenGL");

    //openGL Code
    glClearColor(0.0, 1.0, 0.0, 0.0 );
    glClear(GL_COLOR_BUFFER_BIT);
    glOrtho(-5.0, 15.0, -5, 15.0, -1.0, 1.0);
    glColor3f(1.0, 0.0, 0.0);
    glEnable(GL_POINT_SMOOTH);
    glPointSize(5);
    //triangle points
    point2 p1, p2, p3;

    p1[0] = 5.0;
    p1[1] = 0.0;    

    p2[0] = 10.0;
    p2[1] = 0.0;

    p3[0] = 7.5;
    p3[1] = 10.0;

    init(p1,p2,p3);
//    glBegin(GL_TRIANGLES);
//        glVertex2fv(p1);
//        glVertex2fv(p2);
//        glVertex2fv(p3);
//    glEnd();
    for(int j=0 ; j< 10000; j++){
        display();
    }

    glFlush();
    glutSwapBuffers();
    glutMainLoop();
    return 0;
}

void init(point2 p1, point2 p2, point2 p3){  
    myTriangle t;
    t[0][0] = p1[0];
    t[0][1] = p1[1];

    t[1][0] = p2[0];
    t[1][1] = p2[1];

    t[2][0] = p3[0];
    t[2][1] = p3[1];

    triangle = &t;    
}

void display(void){
    static point2 p = {1,1};
    int i;

    //pick a random vertex    
    i = rand() % 3;  //i in the range 0 to 2

    p[0] = (p[0] + *triangle[i][0])/2;
    p[1] = (p[1] + *triangle[i][1])/2;
    cout << p[0] << ' , ' << p[1] << endl;
    //display new points
    glBegin(GL_POINTS);
        glVertex2fv(p);
    glEnd();


}

4 Answers4

4
void init(point2 p1, point2 p2, point2 p3){  
    myTriangle t;
    ..
    triangle = &t;
} // Life time of 't' ends here.

The problem is triangle has reference to local variable which leads to undefined behavior.

Mahesh
  • 34,573
  • 20
  • 89
  • 115
  • the problem still exists, but this time the values changed only after first reference and after that remain constant. – Abdalla Essam Ali Mar 10 '16 at 22:10
  • Please read the thread - [Can local variables memory be accessed outside its scope ?](http://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope) – Mahesh Mar 10 '16 at 22:16
3

You are assigning an address of a local variable in your init function. When init returns, that address you've assigned is no longer valid, since the variable tied to that address is local.

void init(point2 p1, point2 p2, point2 p3)
{  
    myTriangle t;
    t[0][0] = p1[0];
    t[0][1] = p1[1];

    t[1][0] = p2[0];
    t[1][1] = p2[1];

    t[2][0] = p3[0];
    t[2][1] = p3[1];

    triangle = &t;    // <-- assigning address of local variable.  No good.
}

The issue with your code is that you do not have a myTriangle that is alive for you to assign to the triangle pointer.

Your current code sets triangle to a myTriangle that is going to die off as soon as the init function returns, and nothing in your code indicates where this "alive" object that triangle will point to will exist.

So in reality, you're asking for a solution that only you can really come up with. We can suggest things like allocate a global myTriangle, where the address won't get invalidated, or use new myTriangle within the function to dynamically allocate one (which then leads to other issues), or some other answer similar to that. However that is a design decision you have to make.

PaulMcKenzie
  • 34,698
  • 4
  • 24
  • 45
0
typedef GLfloat point2[2]; 
typedef GLfloat myTriangle[3][2]; // EDIT
myTriangle *triangle;

Compiles and runs fine, should do what you want.

  • it still changed after first call, i just try to print them 10 times, in the first time it print the correct value, but then they change and remain the same after that. `cout<< *triangle[0][0]< – Abdalla Essam Ali Mar 10 '16 at 22:13
0

In addition to Mahesh's answer, *triangle[i][0] probably doesn't do what you want. It's equivalent to *(triangle[i][0]). Since triangle points to a single triangle this is UB if i > 0. You need to do (*triangle)[i][0] instead. This will dereference the pointer first.

Kevin
  • 6,993
  • 1
  • 15
  • 24