简体   繁体   中英

Memory leak issue c++ program

I have been struggling with a memory leak, I am writing a program to read a certain image colours.

Code: http://ideone.com/dcU5Su

Problem : I am unable to find out the source of memory leak/leaks.

What I tried : I ran the program through Valgrind. Amongst a lot of unprocessible information, below are the errors I could make out:

  • Invalid write of size 4 [There were 3 of these]
  • Conditional jump or move depends on uninitialised value(s)
  • Syscall param write(buf) points to uninitialised byte(s)

Looking at the above errors, I think the issue has something to do with improper initialization. But I am unable to see where.

You should not be doing manual memory management like this. Use a vector:

#include <iostream>
#include <sstream>
#include <vector>

struct Image {
    unsigned int l;
    unsigned int b; 
    unsigned int h;  
};

int main()
{
    using namespace std;

    std::vector<Image> image;

    std::string line;
    while(getline(cin,line))
    {
        if(rand()%2)
        {
            istringstream iss(line);

            Image img;
            while (iss >> img.l >> img.b >> img.h)
            {
                image.push_back(img);
            }
        }
    }
}

Update

Since you didn't provide feedback (why the delete[] appeared to be inside the loop in your sample), the best I can do is post a refactored suggestion including the fixes/improvements I would make:

Live On Coliru

#include <iostream>
#include <sstream>

#include <cstring>
#include <cassert>

struct Image {
    unsigned int l;
    unsigned int b; 
    unsigned int h;  
};

class Images {
  private:
    size_t capacity;
    size_t size;

    Image *images;

    Images& operator=(Images const&); // not supported
    Images(Images const&);            // not supported

    void autogrow() {
        if (size >= capacity) {
            int newCapacity = capacity * 2;
            Image* newImage = new Image[newCapacity];
            std::cout << "growing " << capacity << " -> " << newCapacity << "\n";

            //only available in c++11:
            static_assert(std::is_pod<Image>::value, "you're screwed");
            memcpy(newImage, images, size * sizeof(Image));

            capacity = newCapacity;
            delete[] images;
            images = newImage;

        }
    }

  public:
    Images() : capacity(1), size(0), images(new Image[capacity]) { 
        assert(images);
    };
    ~Images() {
        delete[] images;
    }

    Image& insert(Image const& img) {
        autogrow();
        assert(size<capacity);
        return images[size++] = img;
    }

};

int main()
{
    using namespace std;

    Images collection;

    std::string line;
    while(getline(cin,line))
    {
        if(true) {
            istringstream iss(line);

            Image cur;
            while (iss >> cur.l >> cur.b >> cur.h) {
                collection.insert(cur);
            }
        }
    }
}

Prints, eg

od /dev/urandom -Anone -t u4 -w36 | head -1000 | ./a.out
growing 1 -> 2
growing 2 -> 4
growing 4 -> 8
growing 8 -> 16
growing 16 -> 32
growing 32 -> 64
growing 64 -> 128
growing 128 -> 256
growing 256 -> 512
growing 512 -> 1024
growing 1024 -> 2048
growing 2048 -> 4096

I guess when while (iss >> image[j].l >> image[j].b >> image[j].h) is executed when passing through the second iteration of the outer while loop, the image pointer is not valid since you deleted it in the previous iteration.

So, after delete[] ing image for the second time (after the inner while loop), you should reset your variables (as if you were re-entring the outer while loop for the first time.

// reset
delete[] (image);
capacity = 1;
size = 0;
j = 0;
image = new Image[capacity];

Or, you should put this "reset" block just at the beginning of the outer while (and get rid of the initialization before it).

I don't know the logic of the whole program, but I'd assume that this is the desired behavior...

EDIT : so the problem can be solved by moving size++; just above if (size >= capacity) (kudos to @sehe for finding the origin of the memory violation :) )

size++;
if (size >= capacity)
{

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM