问题
I'm creating a tree of dynamic objects. The Node class has a vector to store the child nodes, among the other class variables:
std::vector<Node*> child;
The class destructor deletes all the dynamically allocated class variables, and then deletes the child nodes:
~Node() {
//Deleting the other variables
.
.
.
//Deleting the child nodes
for(int i = 0; i < child.size(); i++) {
delete child[i];
}
}
My class has a method that creates a tree of a given height, in which the current node is the root node:
void createTree(int height) {
if(height == 0) {
return;
}
for(int i = 0; i < numberOfChildNodes; i++) {
child.push_back(new Node());
child[i]->createTree(height - 1);
}
}
This class has another method where I create a tree with height = 3, then I delete the entire tree and create another one with height = 4, then I delete the entire tree and create one with height = 5, and so on, until a memory limit is reached:
void highestTreePossible() {
int i, height = 3;
struct sysinfo memInfo;
while(true) {
createTree(height);
sysinfo (&memInfo);
if(memInfo.freeram > limit) {
std::cout << "Highest tree possible: height = " << height;
break;
}
for(i = 0; i < child.size(); i++) {
delete child[i];
}
child.clear();
height++;
}
for(i = 0; i < child.size(); i++) {
delete child[i];
}
child.clear();
}
The problem is, when I check the memory after running the method highestTreePossible(), there's a lot of memory allocated, which isn't supposed to happen, because I deleted everything. Why is my code leaking memory?
回答1:
It's not leaking; you're not using a valid test for this kind of thing. Modern operating systems have complex memory management, and you may observe a process "holding on" to more memory than you think it needs at any given time. Rest assured, it is available to the rest of the system when required.
If you're concerned about memory, you need to observe a constant, consistent rise in consumption for your process over a significant period of time, or hook into the actual allocators used by your program itself. A great way to do this is using a diagnostic tool like massif, which ships with Valgrind (if you're on a compatible system). There are some great ways to visualise that.
回答2:
If you're on a Linux system, you can try to use valgrind to reliably check if your code has any memory leaks.
e.g. $valgrind --leak-check=full ./node_test
So to answer the question "Why is my code leaking memory?"
There is no memory leak in your code as I tested/checked it with valgrind report (e.g. "All heap blocks were freed -- no leaks are possible").
However, I seem to notice some problem in the line containing the exit condition if(memInfo.freeram > limit)
since memInfo.freeram
value is expected to be decreasing as the tree grows. And that your goal is to keep the tree growing (hence memInfo.freeram
will also be shrinking) "until a memory limit is reached" as you've mentioned above or "until the memInfo.freeram
falls below a certain limit" as I rephrased it.
So I expect that the correct exit condition should supposedly be the opposite if(memInfo.freeram < limit).
Hope this helps.
PS. It's also a good practice to use smart pointers (e.g. std::unique_ptr, std::shared_ptr) to avoid memory leaks.
来源:https://stackoverflow.com/questions/61892960/why-is-my-program-leaking-memory-working-with-trees-in-c