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:
#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.