Alberto
Alberto

Reputation: 3

Memory reallocation causes segmentation fault on loop

What I'm doing here is basically joining to a global array (optimisedMesh) some smaller arrays (Bx, By, and Bz). As you can see the content and size of Bx, By and Bz is set on the b and c loops. Once they are fully defined they are joined to optimisedMesh. This process should happen every "a" for loop.

I've found two problems trying this. The first one is that when I call free(Bx); once I've finished needing this array, the debugger returns me a segmentation fault, I'm not sure why.

The second one happens on the second loop of the "a" for loop. On the first loop the realloc seems to work fine, but on the second it returns the 0x0 address, which causes a segmentation fault further in the code.

Also, I've ommited the By and Bz code because it looks exactly the same as Bx.

Thanks for your time.

    int* LBxIA = (int*) calloc (1,sizeof(int*));    int* LBxIB = (int*) calloc (1,sizeof(int*)); int* LByIA = (int*) calloc (1,sizeof(int*)); int* LByIB = (int*) calloc (1,sizeof(int*)); int* LBzIA = (int*) calloc (1,sizeof(int*)); int* LBzIB = (int*) calloc (1,sizeof(int*));
    int* LBxFA = (int*) calloc (1,sizeof(int*));    int* LBxFB = (int*) calloc (1,sizeof(int*)); int* LByFA = (int*) calloc (1,sizeof(int*)); int* LByFB = (int*) calloc (1,sizeof(int*)); int* LBzFA = (int*) calloc (1,sizeof(int*)); int* LBzFB = (int*) calloc (1,sizeof(int*));

    Quad** Bx = (Quad**) calloc(1,sizeof(Quad*));

    int maxSize = Math::maxof(xLenght,yLenght,zLenght);
    for(int a = 0; a < maxSize; a++){
        int BxCount = 0; int ByCount = 0; int BzCount = 0;
        Bx = (Quad**) realloc(Bx,sizeof(Quad*));

        for(int b = 0; b < maxSize; b++){   
            for(int c = 0; c < maxSize; c++){
                //Bx
                if(a <xLenght && b < yLenght && c < zLenght){
                    if(cubes[a][b][c] != nullptr){
                        if(!cubes[a][b][c]->faces[FACE_LEFT].hidden){
                            if(!LBxIA){
                                LBxIA = new int(c);
                            }else{
                                LBxFA = new int(c);
                            }
                        }else{
                            if(LBxIA && LBxFA){
                                BxCount++;
                                Bx = (Quad**) realloc(Bx, BxCount * sizeof(Quad*));
                                Bx[BxCount - 1] = new Quad(Vector3(a,b,*LBxIA),Vector3(a,b,*LBxFA),Vector3(a,b+1,*LBxIA),Vector3(a,b+1,*LBxFA));
                                LBxIA = nullptr;
                                LBxFA = nullptr;
                            }
                        }
                    }else{
                        if(LBxIA && LBxFA){
                            BxCount++;
                            Bx = (Quad**) realloc(Bx, BxCount * sizeof(Quad*));
                            Bx[BxCount-1] = new Quad(Vector3(a,b,*LBxIA),Vector3(a,b,*LBxFA),Vector3(a,b+1,*LBxIA),Vector3(a,b+1,*LBxFA));
                            LBxIA = nullptr;
                            LBxFA = nullptr;

                        }
                        if(LBxIB && LBxFB){
                            BxCount++;
                            Bx = (Quad**) realloc(Bx, BxCount * sizeof(Quad*));
                            Bx[BxCount-1] = new Quad(Vector3(a+1,b,*LBxIB),Vector3(a+1,b,*LBxFB),Vector3(a+1,b+1,*LBxIB),Vector3(a+1,b+1,*LBxFB));
                            LBxIB = nullptr;
                            LBxFB = nullptr;
                        }
                    }
                }
            }
        }

        optimisedMeshCount += (BxCount + ByCount + BzCount)*sizeof(Quad*);
        optimisedMesh = (Quad**) realloc(optimisedMesh, optimisedMeshCount);
        copy(Bx, Bx + BxCount*sizeof(Quad*), optimisedMesh + (optimisedMeshCount - (BxCount + ByCount + BzCount)*sizeof(Quad*)));
        copy(By, By + ByCount*sizeof(Quad*), optimisedMesh + (optimisedMeshCount - (BxCount + ByCount + BzCount)*sizeof(Quad*)) + BxCount*sizeof(Quad*));//TODO Aquí error
        copy(Bz, Bz + BzCount*sizeof(Quad*), optimisedMesh + (optimisedMeshCount - (BxCount + ByCount + BzCount)*sizeof(Quad*)) + BxCount*sizeof(Quad*) + ByCount*sizeof(Quad*));
        free(Bx);
    }

Upvotes: 0

Views: 215

Answers (1)

Olaf Dietsche
Olaf Dietsche

Reputation: 74078

I guess, the problem is with the three copy lines.

copy expects begin and end of some container or memory range. In your case you provide Bx, which is fine, and Bx + BxCount*sizeof(Quad*), which is way beyond the end of Bx memory.

This is because Bx + 1 is not Bx + 1 byte, but &Bx[1], which is the second element. Equally, Bx + BxCount would be the "end" as expected by copy.

This means Bx + BxCount*sizeof(Quad*) is, on a 64 bit system, eight times as much beyond the end of Bx memory range. Same goes for optimisedMesh, By and Bz. As a consequence, you copy too many elements and as a result get memory corruption.


Using std::vector and storing Quads instead of pointers to Quad

std::vector<Quad> Bx, By, Bz, optimisedMesh;
for (int a = 0; a < maxSize; a++) {
    Bx.clear();
    for (int b = 0; b < maxSize; b++) {
        for (int c = 0; c < maxSize; c++) {
            // ...
            Quad qx(Vector3(a,b,*LBxIA),
                   Vector3(a,b,*LBxFA),
                   Vector3(a,b+1,*LBxIA),
                   Vector3(a,b+1,*LBxFA));
            Bx.push_back(qx);
            // ...
        }
    }

    std::copy(Bx.begin(), Bx.end(), std::back_inserter(optimizedMesh));
    std::copy(By.begin(), By.end(), std::back_inserter(optimizedMesh));
    std::copy(Bz.begin(), Bz.end(), std::back_inserter(optimizedMesh));
}

As you can see, no explicit allocation, reallocation or freeing of memory, no counting of elements.


Unrelated, but you must also pay attention to LBxIA = new int(c); and LBxIA = nullptr;, which leaks memory.

Upvotes: 3

Related Questions