cpp 代码中的堆泄漏
Heap Leak in a cpp code
我正在做一个名为无线网络拓扑的项目。它使用图形作为数据结构。我已经提出建议,但面临堆泄漏问题。请问有人可以帮助解决这个错误吗?在哪里调用删除操作员?附cpp代码:
#include <string>
#include <ctime>
#include <cstdlib>
#include <iostream>
#include "myGraph.h"
#include "wirelessNetwork.h"
using namespace std;
void main()
{
srand(time(NULL));
/* First part of the experiments */
for (int i = 500; i <= 950; i += 50)
{
wirelessNetwork *g = new wirelessNetwork(10, i);
std::cout << (L"For network with n=") << i << (L": ") << std::endl;
double average = (static_cast<double>(g->graph->numEdges) / (static_cast<double>(g->graph->numVertices)));
std::cout << (L" The average degree is ") << average << std::endl;
std::cout << (L" The maximum degree is ") << g->getMaxDegree() << std::endl;
/* Perform topology control */
g->topologyControl();
std::cout << (L" After topology control: ") << std::endl;
average = (static_cast<double>(g->graph->numEdges)) / (static_cast<double>(g->graph->numVertices));
std::cout << (L" The average degree is ") << average << std::endl;
std::cout << (L" The maximum degree is ") << g->getMaxDegree() << std::endl;
std::cout << std::endl;
}
/* Second part of the experiments */
wirelessNetwork *g = new wirelessNetwork(10, 1000);
std::cout << (L"***********************************") << std::endl;
for (int i = 1; i <= 10; i++)
{
/* Randomly pick two vertices as the source and destination */
int i1 = static_cast<int>(1000 * rand());
int i2 = static_cast<int>(1000 * rand());
string nameTemp = "a";
string node1 = nameTemp + std::to_string(i1);
string node2 = nameTemp + std::to_string(i2);
//ORIGINAL LINE: String[] route = g.compassRouting(node1, node2);
string *route = g->compassRouting(node1, node2);
std::cout << std::endl;
std::cout << (L"Path generated from ") << node1 << (L" to ") << node2 << (L":") << std::endl;
for (int k = 0; k < route->length(); k++)
{
std::cout << (L" ") << route[k];
}
if (node2 != route[route->length() - 1])
{
std::cout << std::endl;
std::cout << (L" No route found...") << std::endl;
}
std::cout << std::endl;
std::cout << (L" Length of the path generated is ") << (route->length() - 1) << std::endl;
}
/* Third part of the experiments */
g->topologyControl();
std::cout << std::endl;
std::cout << (L"***********************************") << std::endl;
std::cout << (L"After topology control...") << std::endl;
for (int i = 1; i <= 10; i++)
{
int i1 = static_cast<int>(1000 * rand());
int i2 = static_cast<int>(1000 * rand());
string nameTemp = "a";
string node1 = nameTemp + std::to_string(i1);
string node2 = nameTemp + std::to_string(i2);
//ORIGINAL LINE: String[] route = g.compassRouting(node1, node2);
string *route = g->compassRouting(node1, node2);
std::cout << std::endl;
std::cout << (L"Path generated from ") << node1 << (L" to ") << node2 << (L":") << std::endl;
for (int k = 0; k < route->length(); k++)
{
std::cout << (L" ") << route[k];
}
if (node2 != route[route->length() - 1])
{
std::cout << std::endl;
std::cout << (L" No route found...");
}
std::cout << std::endl;
std::cout << (L" Length of the path is ") << (route->length() - 1) << std::endl;
}
}
`
确定何时调用 delete 运算符的一种方法是检查指针变量何时超出范围并在它超出范围之前将其删除。
void func()
{
ClassA* ptr1 = new ClassA;
//do NULL check for ptr1 and do stuff
delete ptr1;
//here ptr1 will lose scope.
//If not deleted, it will become a memory leak.
}
在某些情况下,我们无法删除指针,即使它超出了范围。例如,如果我们将新指针值存储在其他指针变量中,并且第二个变量仍然没有超出范围。
void func(bool IsReady)
{
ClassA* ptr1 = NULL;
if(IsReady)
{
ClassA* ptr2 = new ClassA;
//do stuff
ptr1 = ptr2;
//in this case, even though ptr2 will lose scope outside this block,
//the ptr2 value is assigned to ptr1 which is does not lose scope outside this block.
}
//here ptr1 will still contain the data we copied in the if block,
//else it will be NULL. After use of ptr1 is complete, do a NULL check and delete.
if(ptr1 != NULL)
delete ptr1;
}
在你的情况下,我只看到第一种类型,并且只有 2 个地方调用了 new 运算符。
在第一种情况的适当位置调用删除运算符,就在 g 超出范围之前:
/* First part of the experiments */
for (int i = 500; i <= 950; i += 50)
{
wirelessNetwork *g = new wirelessNetwork(10, i);
std::cout << (L"For network with n=") << i << (L": ") << std::endl;
double average = (static_cast<double>(g->graph->numEdges) / (static_cast<double>(g->graph->numVertices)));
std::cout << (L" The average degree is ") << average << std::endl;
std::cout << (L" The maximum degree is ") << g->getMaxDegree() << std::endl;
/* Perform topology control */
g->topologyControl();
std::cout << (L" After topology control: ") << std::endl;
average = (static_cast<double>(g->graph->numEdges)) / (static_cast<double>(g->graph->numVertices));
std::cout << (L" The average degree is ") << average << std::endl;
std::cout << (L" The maximum degree is ") << g->getMaxDegree() << std::endl;
std::cout << std::endl;
//here g loses scope and does not seem to be stored in any other pointer
delete g;
}
对于第二种情况,在函数末尾调用delete。
希望这能解决您关于何时在代码中调用删除的问题。
但是,您可以通过替换以下内容来避免同时调用 new 和 delete:
wirelessNetwork *g = new wirelessNetwork(10, i);
和
wirelessNetwork g(10, i);
并使用 g 访问成员变量。而不是 g->。
例如:g->topologyControl();
应该是 g.topologyControl();
希望这个回答对您有所帮助。
最佳答案是您不应该使用指针或 new 运算符。正如其他人所建议的那样,只需在需要的范围内直接构造对象,这样当它超出范围时就会自动销毁。
这个问题的一个非常常见(但我认为非常糟糕)的答案是在指针超出范围之前立即删除对象 and/or 将所有删除操作放在与相应的新操作。在这种情况下,当这种方法可行时,您几乎总是根本不需要指针或 new。当对象的生命周期与创建它的范围不匹配时,您确实需要一个指针并使用 new 运算符,并且管理对象的生命周期是 C++ 编程的难点之一。在这些情况下没有通用的答案。但是在你遇到这样的问题之前,不要通过毫无意义地使用 new 运算符来创建它。
我正在做一个名为无线网络拓扑的项目。它使用图形作为数据结构。我已经提出建议,但面临堆泄漏问题。请问有人可以帮助解决这个错误吗?在哪里调用删除操作员?附cpp代码:
#include <string>
#include <ctime>
#include <cstdlib>
#include <iostream>
#include "myGraph.h"
#include "wirelessNetwork.h"
using namespace std;
void main()
{
srand(time(NULL));
/* First part of the experiments */
for (int i = 500; i <= 950; i += 50)
{
wirelessNetwork *g = new wirelessNetwork(10, i);
std::cout << (L"For network with n=") << i << (L": ") << std::endl;
double average = (static_cast<double>(g->graph->numEdges) / (static_cast<double>(g->graph->numVertices)));
std::cout << (L" The average degree is ") << average << std::endl;
std::cout << (L" The maximum degree is ") << g->getMaxDegree() << std::endl;
/* Perform topology control */
g->topologyControl();
std::cout << (L" After topology control: ") << std::endl;
average = (static_cast<double>(g->graph->numEdges)) / (static_cast<double>(g->graph->numVertices));
std::cout << (L" The average degree is ") << average << std::endl;
std::cout << (L" The maximum degree is ") << g->getMaxDegree() << std::endl;
std::cout << std::endl;
}
/* Second part of the experiments */
wirelessNetwork *g = new wirelessNetwork(10, 1000);
std::cout << (L"***********************************") << std::endl;
for (int i = 1; i <= 10; i++)
{
/* Randomly pick two vertices as the source and destination */
int i1 = static_cast<int>(1000 * rand());
int i2 = static_cast<int>(1000 * rand());
string nameTemp = "a";
string node1 = nameTemp + std::to_string(i1);
string node2 = nameTemp + std::to_string(i2);
//ORIGINAL LINE: String[] route = g.compassRouting(node1, node2);
string *route = g->compassRouting(node1, node2);
std::cout << std::endl;
std::cout << (L"Path generated from ") << node1 << (L" to ") << node2 << (L":") << std::endl;
for (int k = 0; k < route->length(); k++)
{
std::cout << (L" ") << route[k];
}
if (node2 != route[route->length() - 1])
{
std::cout << std::endl;
std::cout << (L" No route found...") << std::endl;
}
std::cout << std::endl;
std::cout << (L" Length of the path generated is ") << (route->length() - 1) << std::endl;
}
/* Third part of the experiments */
g->topologyControl();
std::cout << std::endl;
std::cout << (L"***********************************") << std::endl;
std::cout << (L"After topology control...") << std::endl;
for (int i = 1; i <= 10; i++)
{
int i1 = static_cast<int>(1000 * rand());
int i2 = static_cast<int>(1000 * rand());
string nameTemp = "a";
string node1 = nameTemp + std::to_string(i1);
string node2 = nameTemp + std::to_string(i2);
//ORIGINAL LINE: String[] route = g.compassRouting(node1, node2);
string *route = g->compassRouting(node1, node2);
std::cout << std::endl;
std::cout << (L"Path generated from ") << node1 << (L" to ") << node2 << (L":") << std::endl;
for (int k = 0; k < route->length(); k++)
{
std::cout << (L" ") << route[k];
}
if (node2 != route[route->length() - 1])
{
std::cout << std::endl;
std::cout << (L" No route found...");
}
std::cout << std::endl;
std::cout << (L" Length of the path is ") << (route->length() - 1) << std::endl;
}
}
`
确定何时调用 delete 运算符的一种方法是检查指针变量何时超出范围并在它超出范围之前将其删除。
void func()
{
ClassA* ptr1 = new ClassA;
//do NULL check for ptr1 and do stuff
delete ptr1;
//here ptr1 will lose scope.
//If not deleted, it will become a memory leak.
}
在某些情况下,我们无法删除指针,即使它超出了范围。例如,如果我们将新指针值存储在其他指针变量中,并且第二个变量仍然没有超出范围。
void func(bool IsReady)
{
ClassA* ptr1 = NULL;
if(IsReady)
{
ClassA* ptr2 = new ClassA;
//do stuff
ptr1 = ptr2;
//in this case, even though ptr2 will lose scope outside this block,
//the ptr2 value is assigned to ptr1 which is does not lose scope outside this block.
}
//here ptr1 will still contain the data we copied in the if block,
//else it will be NULL. After use of ptr1 is complete, do a NULL check and delete.
if(ptr1 != NULL)
delete ptr1;
}
在你的情况下,我只看到第一种类型,并且只有 2 个地方调用了 new 运算符。 在第一种情况的适当位置调用删除运算符,就在 g 超出范围之前:
/* First part of the experiments */
for (int i = 500; i <= 950; i += 50)
{
wirelessNetwork *g = new wirelessNetwork(10, i);
std::cout << (L"For network with n=") << i << (L": ") << std::endl;
double average = (static_cast<double>(g->graph->numEdges) / (static_cast<double>(g->graph->numVertices)));
std::cout << (L" The average degree is ") << average << std::endl;
std::cout << (L" The maximum degree is ") << g->getMaxDegree() << std::endl;
/* Perform topology control */
g->topologyControl();
std::cout << (L" After topology control: ") << std::endl;
average = (static_cast<double>(g->graph->numEdges)) / (static_cast<double>(g->graph->numVertices));
std::cout << (L" The average degree is ") << average << std::endl;
std::cout << (L" The maximum degree is ") << g->getMaxDegree() << std::endl;
std::cout << std::endl;
//here g loses scope and does not seem to be stored in any other pointer
delete g;
}
对于第二种情况,在函数末尾调用delete。
希望这能解决您关于何时在代码中调用删除的问题。
但是,您可以通过替换以下内容来避免同时调用 new 和 delete:
wirelessNetwork *g = new wirelessNetwork(10, i);
和
wirelessNetwork g(10, i);
并使用 g 访问成员变量。而不是 g->。
例如:g->topologyControl();
应该是 g.topologyControl();
希望这个回答对您有所帮助。
最佳答案是您不应该使用指针或 new 运算符。正如其他人所建议的那样,只需在需要的范围内直接构造对象,这样当它超出范围时就会自动销毁。
这个问题的一个非常常见(但我认为非常糟糕)的答案是在指针超出范围之前立即删除对象 and/or 将所有删除操作放在与相应的新操作。在这种情况下,当这种方法可行时,您几乎总是根本不需要指针或 new。当对象的生命周期与创建它的范围不匹配时,您确实需要一个指针并使用 new 运算符,并且管理对象的生命周期是 C++ 编程的难点之一。在这些情况下没有通用的答案。但是在你遇到这样的问题之前,不要通过毫无意义地使用 new 运算符来创建它。