munmap_chunk() - Invalid pointer error

22,897

I think my previous post on similar topic would be useful.

https://stackoverflow.com/a/22658693/2724703

From your Valgrind report, it look like your program is doing memory corruption due to overflow. This does not seems like "double free" error(this is overflow scenario). You have mentioned that sometime valgrind is not reporting any error this makes this problem more difficult. However there is certainly a memory corruption and you must fix them. Memory error sometime occur intermittent due to various reason(different input parameter, multi-threaded, change of execution sequence).

Share:
22,897
Actimia
Author by

Actimia

Updated on April 03, 2020

Comments

  • Actimia
    Actimia about 4 years

    I'm writing a renderer using low-level SDL functions to learn how it all works. I am now trying to do polygon drawing, but I run into errors possibly due to my inexperience with C++. When running the code I get a munmap_chunk() - Invalid pointer error. Searching reveals that it is most likely due to free()-ing the memory twice. The error happens when returning from the function. I realize that the error comes from automatically free()ing memory which has been automatically free()d before, but I'm not experienced enough with C++ to spot the error. Any clues?

    My code:

    void DrawPolygon (const vector<vec3> & verts, vec3 color){
    
        // 0. Project to the screen
        vector<ivec2> vertices(verts.size());
        for(int i = 0; i < verts.size(); i++){
            VertexShader(verts.at(i), vertices.at(i));
        }
    
        // 1. Find max and min y-value of the polygon 
        // and compute the number of rows it occupies.
        int miny = vertices[0].y;
        int maxy = vertices[0].y;
    
        for (int i = 1; i < 3; i++){
            if (vertices[i].y < miny){
                miny = vertices[i].y;
            }
            if (vertices[i].y > maxy){
                maxy = vertices[i].y;
            }
        }
    
        int rows = abs(maxy - miny) + 1;
        // 2. Resize leftPixels and rightPixels 
        // so that they have an element for each row. 
    
        vector<ivec2> leftPixels(rows);
        vector<ivec2> rightPixels(rows);
    
        // 3. Initialize the x-coordinates in leftPixels 
        // to some really large value and the x-coordinates 
        // in rightPixels to some really small value. 
    
        for(int i = 0; i < rows; i++){
            leftPixels[i].x = std::numeric_limits<int>::max();
            rightPixels[i].x = std::numeric_limits<int>::min();
            leftPixels[i].y = miny + i;
            rightPixels[i].y = miny + i;
        }
    
        // 4. Loop through all edges of the polygon and use 
        // linear interpolation to find the x-coordinate for 
        // each row it occupies. Update the corresponding 
        // values in rightPixels and leftPixels.
    
        for(int i = 0; i < 3; i++){
            ivec2 a = vertices[i];
            ivec2 b = vertices[(i+1)%3];
    
            // find the number of pixels to draw
            ivec2 delta = glm::abs(a - b);
            int pixels = glm::max(delta.x, delta.y) + 1;
    
            // interpolate to find the pixels
            vector<ivec2> line (pixels);
            Interpolate(a, b, line);
    
            for(int j = 0; j < pixels; j++){
                ivec2 p = line[j];
                ivec2 cmpl = leftPixels[p.y - miny];
                ivec2 cmpr = rightPixels[p.y - miny];
    
                if(p.x < cmpl.x){
                    leftPixels[p.y - miny].x = p.x;
                    //leftPixels[p.y - miny] = cmpl;
                }
    
                if(p.x > cmpr.x){
                    rightPixels[p.y - miny].x = p.x;
                    //cmpr.x = p.x;
                    //rightPixels[p.y - miny] = cmpr;
                }
            }
        }
    
        for(int i = 0; i < leftPixels.size(); i++){
            ivec2 l = leftPixels.at(i);
            ivec2 r = rightPixels.at(i);
    
            // y coord the same, iterate over x
            int y = l.y;
            for(int x = l.x; x <= r.x; x++){
                PutPixelSDL(screen, x, y, color);
            }
        }
    }
    

    Using valgrind gives me this output (this is the first error it reports). Weirdly, the program recovers and keeps running with the expected result, apparently not getting the same error again:

    ==5706== Invalid write of size 4
    ==5706==    at 0x40AD61: DrawPolygon(std::vector<glm::detail::tvec3<float>, std::allocator<glm::detail::tvec3<float> > > const&, glm::detail::tvec3<float>) (in /home/actimia/prog/dgi14/lab3/ThirdLab)
    ==5706==    by 0x409C78: Draw() (in /home/actimia/prog/dgi14/lab3/ThirdLab)
    ==5706==    by 0x409668: main (in /home/actimia/prog/dgi14/lab3/ThirdLab)
    
  • Actimia
    Actimia about 10 years
    Thank you. It was an out of range error due to interpolation rounding when going "backwards".