vector2d's = operator is overwriting my stack variable

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
Apickx
Posts: 3
Joined: Mon May 28, 2018 7:40 pm

vector2d's = operator is overwriting my stack variable

Post by Apickx »

Edit: Literal seconds after posting I figured it out; my array was too small. Thanks everyone :oops:

I've been stuck on this for a while, I suspect my problem is not with irrlicht, but with something more fundamental to C/C++

I'm using https://github.com/syoyo/tinyobjloader-c/ to basically re-implement COBJMeshFileFileLoader.cpp (I already have the model in memory, it is received over the network, so writing then reading a temporary file seems wasteful). I know the code below is pretty messy and can be simplified, I'll refactor it once I get it working.

I have the following code

Code: Select all

 
static void newbphysmodel (...){
 
    //Create the scene node
    IMeshBuffer *buf = new CDynamicMeshBuffer(E_VERTEX_TYPE::EVT_STANDARD,E_INDEX_TYPE::EIT_16BIT);
    tinyobj_attrib_t attrib;
    printf("At the very beginning, attrib is %p\n",(void*)&attrib);
    tinyobj_shape_t *shapes = NULL;
    size_t meshcount;
    tinyobj_material_t *materials = NULL;
    size_t num_materials;
 
    //load the data from the network
    char *objdata = ...;
    size_t data_len = ...;
 
    //Parse the data into a tinyobj
    int err = tinyobj_parse_obj(&attrib, &shapes, &meshcount, &materials, &num_materials, objdata, data_len, TINYOBJ_FLAG_TRIANGULATE);
    if(err != TINYOBJ_SUCCESS){
        printf("Tinyobj failed to load model\n");
    }
 
    printf("Obj attrib:\n\tnum_vertices:%d\n\tnum_normals:%d\n\tnum_texcoords:%d\n\tnum_faces:%d\n\tnum_face_num_verts:%d\n",
            attrib.num_vertices, attrib.num_normals, attrib.num_texcoords, attrib.num_faces, attrib.num_face_num_verts);
    S3DVertex verts[attrib.num_face_num_verts];
    u16 indicies[attrib.num_faces];
    size_t index_c = 0;
 
    for(int i = 0; i < attrib.num_faces; i+=3){
        printf("pre i: %u / %d\n",i,attrib.num_faces);
        tinyobj_vertex_index_t fac1 = attrib.faces[i + 0];
        tinyobj_vertex_index_t fac2 = attrib.faces[i + 1];
        tinyobj_vertex_index_t fac3 = attrib.faces[i + 2];
        printf("Verts:\n\tPosition, normal, texture\n\t(%8d %7d %7d)\n\t(%8d %7d %7d)\n\t(%8d %7d %7d)\n",fac1.v_idx,fac1.vn_idx,fac1.vt_idx,fac2.v_idx,fac2.vn_idx,fac2.vt_idx,fac3.v_idx,fac3.vn_idx,fac3.vt_idx);
 
        printf("post i1: %u / %d\n",i,attrib.num_faces);
        float f1px, f1py, f1pz;
        f1px = attrib.vertices[(3 * fac1.v_idx) + 0];
        f1py = attrib.vertices[(3 * fac1.v_idx) + 1];
        f1pz = attrib.vertices[(3 * fac1.v_idx) + 2];
        float f1nx, f1ny, f1nz;
        f1nx = attrib.normals[(3 * fac1.vn_idx) + 0];
        f1ny = attrib.normals[(3 * fac1.vn_idx) + 1];
        f1nz = attrib.normals[(3 * fac1.vn_idx) + 2];
 
        printf("post i2: %u / %d\n",i,attrib.num_faces);
        float f2px, f2py, f2pz;
        f2px = attrib.vertices[(3 * fac2.v_idx) + 0];
        f2py = attrib.vertices[(3 * fac2.v_idx) + 1];
        f2pz = attrib.vertices[(3 * fac2.v_idx) + 2];
        float f2nx, f2ny, f2nz;
        f2nx = attrib.normals[(3 * fac2.vn_idx) + 0];
        f2ny = attrib.normals[(3 * fac2.vn_idx) + 1];
        f2nz = attrib.normals[(3 * fac2.vn_idx) + 2];
 
        printf("post i3: %u / %d\n",i,attrib.num_faces);
        float f3px, f3py, f3pz;
        f3px = attrib.vertices[(3 * fac3.v_idx) + 0];
        f3py = attrib.vertices[(3 * fac3.v_idx) + 1];
        f3pz = attrib.vertices[(3 * fac3.v_idx) + 2];
        float f3nx, f3ny, f3nz;
        f3nx = attrib.normals[(3 * fac3.vn_idx) + 0];
        f3ny = attrib.normals[(3 * fac3.vn_idx) + 1];
        f3nz = attrib.normals[(3 * fac3.vn_idx) + 2];
 
        printf("post i4: %u / %d\n",i,attrib.num_faces);
        printf("Triangle %d:\n\t\
    Positions:\n\t\t\
        (%f %f %f)\n\t\t\
        (%f %f %f)\n\t\t\
        (%f %f %f)\n\t\
    Normals:\n\t\t\
        (%f %f %f)\n\t\t\
        (%f %f %f)\n\t\t\
        (%f %f %f)\n",((int)i)/3,f1px,f1py,f1pz,f2px,f2py,f2pz,f3px,f3py,f3pz,f1nx,f1ny,f1nz,f2nx,f2ny,f2nz,f3nx,f3ny,f3nz);
        //float 
 
        printf("post i5.1: %u / %d\n",i,attrib.num_faces);
        verts[i + 0] = S3DVertex(f1px,f1py,f1pz,f1nx,f1ny,f1nz,SColor(255,255,255,255),0,0);
        printf("post i5.2: %u / %d\n",i,attrib.num_faces);
        verts[i + 1] = S3DVertex(f2px,f2py,f2pz,f2nx,f2ny,f2nz,SColor(255,255,255,255),0,0);
        printf("post i5.3: %u / %d\n",i,attrib.num_faces);
        verts[i + 2] = S3DVertex(f3px,f3py,f3pz,f3nx,f3ny,f3nz,SColor(255,255,255,255),0,0);
        printf("post i6: %u / %d\n",i,attrib.num_faces);
        indicies[index_c] = i;
        index_c++;
        indicies[index_c] = i + 1;
        index_c++;
        indicies[index_c] = i + 2;
        index_c++;
        printf("post ilast: %u / %d\n",i,attrib.num_faces);
    }
    printf("indicies:\n");
    for(size_t i = 0; i < index_c; i++){
        printf("%d ",indicies[i]);
    }
    printf("\n");
 
    buf->append(verts, attrib.num_face_num_verts, indicies, (u32)index_c);
    buf->recalculateBoundingBox();
    SMesh *gmesh = new SMesh();
    gmesh->addMeshBuffer(buf);
    gmesh->recalculateBoundingBox();
 
    printf("Creating client pysbox at %f %f %f\n",x,y,z);
    ISceneNode *node = smgr->addMeshSceneNode(gmesh,0,-1,vector3df(x,y,z));
    :
    :
}
 
Which produces console output:

Code: Select all

 
At the very beginning, attrib is 0000000000F8FA00
Obj attrib:
        num_vertices:8
        num_normals:6
        num_texcoords:0
        num_faces:36
        num_face_num_verts:12
pre i: 0 / 36
Verts:
        Position, normal, texture
        (       0       0 -2147483648)
        (       1       0 -2147483648)
        (       2       0 -2147483648)
post i1: 0 / 36
post i2: 0 / 36
post i3: 0 / 36
post i4: 0 / 36
Triangle 0:
                Positions:
                                (8.000000 -8.000000 -8.000000)
                                (8.000000 -8.000000 8.000000)
                                (-8.000001 -8.000000 7.999999)
                Normals:
                                (0.000000 -1.000000 0.000000)
                                (0.000000 -1.000000 0.000000)
                                (0.000000 -1.000000 0.000000)
post i5.1: 0 / 36
post i5.2: 0 / 36
post i5.3: 0 / 36
post i6: 0 / 36
post ilast: 0 / 36
pre i: 3 / 36
Verts:
        Position, normal, texture
        (       0       0 -2147483648)
        (       2       0 -2147483648)
        (       3       0 -2147483648)
post i1: 3 / 36
post i2: 3 / 36
post i3: 3 / 36
post i4: 3 / 36
Triangle 1:
                Positions:
                                (8.000000 -8.000000 -8.000000)
                                (-8.000001 -8.000000 7.999999)
                                (-7.999997 -8.000000 -8.000003)
                Normals:
                                (0.000000 -1.000000 0.000000)
                                (0.000000 -1.000000 0.000000)
                                (0.000000 -1.000000 0.000000)
post i5.1: 3 / 36
post i5.2: 3 / 36
post i5.3: 3 / 36
post i6: 3 / 36
post ilast: 3 / 36
pre i: 6 / 36
Verts:
        Position, normal, texture
        (       4       1 -2147483648)
        (       7       1 -2147483648)
        (       6       1 -2147483648)
post i1: 6 / 36
post i2: 6 / 36
post i3: 6 / 36
post i4: 6 / 36
Triangle 2:
                Positions:
                                (8.000004 8.000000 -7.999996)
                                (-8.000000 8.000000 -8.000000)
                                (-8.000003 8.000000 7.999997)
                Normals:
                                (0.000000 1.000000 0.000000)
                                (0.000000 1.000000 0.000000)
                                (0.000000 1.000000 0.000000)
post i5.1: 6 / 36
post i5.2: 6 / 36
post i5.3: 6 / 36
post i6: 6 / 36
post ilast: 6 / 36
pre i: 9 / 36
Verts:
        Position, normal, texture
        (       4       1 -2147483648)
        (       6       1 -2147483648)
        (       5       1 -2147483648)
post i1: 9 / 36
post i2: 9 / 36
post i3: 9 / 36
post i4: 9 / 36
Triangle 3:
                Positions:
                                (8.000004 8.000000 -7.999996)
                                (-8.000003 8.000000 7.999997)
                                (7.999995 8.000000 8.000005)
                Normals:
                                (0.000000 1.000000 0.000000)
                                (0.000000 1.000000 0.000000)
                                (0.000000 1.000000 0.000000)
post i5.1: 9 / 36
post i5.2: 9 / 36
post i5.3: 9 / 36
post i6: 9 / 36
post ilast: 9 / 36
pre i: 12 / 36
Verts:
        Position, normal, texture
        (       0       2 -2147483648)
        (       4       2 -2147483648)
        (       5       2 -2147483648)
post i1: 12 / 36
post i2: 12 / 36
post i3: 12 / 36
post i4: 12 / 36
Triangle 4:
                Positions:
                                (8.000000 -8.000000 -8.000000)
                                (8.000004 8.000000 -7.999996)
                                (7.999995 8.000000 8.000005)
                Normals:
                                (1.000000 0.000000 0.000000)
                                (1.000000 0.000000 0.000000)
                                (1.000000 0.000000 0.000000)
post i5.1: 12 / 36
post i5.2: 12 / 36
post i5.3: 12 / 36
post i6: 12 / 36
post ilast: 12 / 36
pre i: 15 / 36
Verts:
        Position, normal, texture
        (       0       2 -2147483648)
        (       5       2 -2147483648)
        (       1       2 -2147483648)
post i1: 15 / 36
post i2: 15 / 36
post i3: 15 / 36
post i4: 15 / 36
Triangle 5:
                Positions:
                                (8.000000 -8.000000 -8.000000)
                                (7.999995 8.000000 8.000005)
                                (8.000000 -8.000000 8.000000)
                Normals:
                                (1.000000 0.000000 0.000000)
                                (1.000000 0.000000 0.000000)
                                (1.000000 0.000000 0.000000)
post i5.1: 15 / 36
post i5.2: 15 / 36
post i5.3: 15 / 0
post i6: 15 / 0
post ilast: 15 / 0
pre i: 18 / 0
 
Console output shows that my `attrib` variable's `num_faces` is 0 after the 5th time through the loop. Specifically, it's set to 0 after the line

Code: Select all

 
 verts[i + 1] = S3DVertex(f2px,f2py,f2pz,f2nx,f2ny,f2nz,SColor(255,255,255,255),0,0);
 
I had no idea why this was happening since I don't write to attrib ANYWHERE after it's created. After firing up (and re-learning) gdb, I stepped through the appropriate line in the code and found:

Code: Select all

 
print attrib
 
print attrib
 
$10 = {num_vertices = 8
 
, num_normals = 6
 
, num_texcoords = 0
 
, num_faces = 36
 
, num_face_num_verts = 12
 
, pad0 = 0
 
, vertices = 0x3f141b0
 
, normals = 0x2f44700
 
, texcoords = 0x2f25340
 
, faces = 0x3f81cc0
 
, face_num_verts = 0x3f40560
 
, material_ids = 0x3f404a0
 
}
 
 
step
 
step
 
irr::core::vector3d<float>::operator= (this=0xf8f9fc, other=...) at lib/irrlicht/include/vector3d.h:38
 
38      vector3d<T>& operator=(const vector3d<T>& other) { X = other.X; Y = other.Y; Z = other.Z; return *this; }
 
print attrib
 
print attrib
 
$11 = {num_vertices = 8
 
, num_normals = 6
 
, num_texcoords = 0
 
, num_faces = 36
 
, num_face_num_verts = 12
 
, pad0 = 0
 
, vertices = 0x3f141b0
 
, normals = 0x2f44700
 
, texcoords = 0x2f25340
 
, faces = 0x3f81cc0
 
, face_num_verts = 0x3f40560
 
, material_ids = 0x3f404a0
 
}
 
 
step
 
step
 
irr::core::vector2d<float>::operator= (this=0xf8fa0c, other=...) at lib/irrlicht/include/vector2d.h:39
 
39    vector2d<T>& operator=(const vector2d<T>& other) { X = other.X; Y = other.Y; return *this; }
 
print attrib
 
print attrib
 
$12 = {num_vertices = 0
 
, num_normals = 0
 
, num_texcoords = 4294967295
 
, num_faces = 36
 
, num_face_num_verts = 12
 
, pad0 = 0
 
, vertices = 0x3f141b0
 
, normals = 0x2f44700
 
, texcoords = 0x2f25340
 
, faces = 0x3f81cc0
 
, face_num_verts = 0x3f40560
 
, material_ids = 0x3f404a0
 
}
 
 
step
 
step
 
newbphysmodel (L=0x1a0378) at src/client/lua_api/phys/cbphysmodel.cpp:165
 
165      printf("post i5.3: %u / %d\
",i,attrib.num_faces);
 
print attrib
 
print attrib
 
$13 = {num_vertices = 0
 
, num_normals = 0
 
, num_texcoords = 4294967295
 
, num_faces = 0
 
, num_face_num_verts = 0
 
, pad0 = 0
 
, vertices = 0x3f141b0
 
, normals = 0x2f44700
 
, texcoords = 0x2f25340
 
, faces = 0x3f81cc0
 
, face_num_verts = 0x3f40560
 
, material_ids = 0x3f404a0
 
}
 
print &attrib
 
print &attrib
 
$14 = (tinyobj_attrib_t *) 0xf8fa00
 
 
print sizeof(attrib)
 
print sizeof(attrib)
 
$15 = 72
 
So my `attrib` starts at 0xf8fa00 and is 72 bytes long, but one of the texture vectors of one of the vertices in verts[] starts at 0xf8fa0c, and when it's attributes are set it's overwriting what I had in attrib. What's going on here? Is this a "use-after-free" bug? How can that be? I allocated attrib, verts[] and indicies[] on the stack!

I ran it multiple times, and it fails in the same place each time.

Any help is appreciated.
CuteAlien
Admin
Posts: 9647
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: vector2d's = operator is overwriting my stack variable

Post by CuteAlien »

Yeah, most of the time I find problems quickly once I start explaining them to someone :-)
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Post Reply