C++ 代码内存泄漏分析:pcl::PointCloud 对象的潜在问题
代码中存在内存泄漏的潜在问题。在循环中,通过new关键字创建了多个pcl::PointCloud<pcl::PointXYZRGB>类型的指针,并将其添加到了clouds1容器中,但在函数结束时没有对这些指针进行释放。
为了避免内存泄漏,可以在函数结束前使用delete关键字释放这些指针,或者使用智能指针(如std::shared_ptr)来管理这些对象的生命周期。
void mintree(std::vector<Edge> result, pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud100)
{
std::copy(result.begin(), result.end(), std::back_inserter(resulta));
int begin6 = 0;
int m = yejian->size();//路径数就是叶尖数
for (int i = 0; i < m; ++i)
{
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>);
clouds1.push_back(cloud);
}
//首先设置循环次数,每次循环都会产生一条路径
for (size_t i = 0; i < yejian->points.size(); ++i)//找不同叶片的循环
{
//创建每条路径的点云指针clouds[i]
pcl::PointCloud<pcl::PointXYZRGB>::Ptr yr1 = clouds1[i];
cout << "路径" << i + 1 << "所有骨架点:" << endl;
pcl::PointXYZRGB& point54 = jinqi;//防止修改掉茎起点
cout << point54;
pcl::PointXYZRGB& point56 = point54;//将搜索的起点统一设置为茎秆的起点
clouds1[i]->push_back(point56);//起点加入路径
double distances = 0;//设置路径的距离
for (int i = 0; i < cloud100->size(); i++)//找一个叶片内不同点的循环,确保不会遗漏边
{
for (auto it = resulta.begin(); it != resulta.end();)//遍历所有生成树的边
{
pcl::PointXYZRGB& point53 = point56;//53表示上一个点的数据
const auto& edge = *it;
pcl::PointXYZRGB p0 = cloud100->points[edge.src];//在点云cloud里面找到该索引对应的点值
pcl::PointXYZRGB p00 = cloud100->points[edge.tgt];
//判断叶尖点与找到边两点是否相同,若相同则将该边加入yr1点云指针,将该边加入容器yr1
if ((point56.x == p0.x) && (point56.y == p0.y) && (point56.z == p0.z))
{
yr1->push_back(p00);//yr1表示储存的路径
distances = distances + euclideanDistance(point56, p00);
point56 = p00;
}
else if ((point56.x == p00.x) && (point56.y == p00.y) && (point56.z == p00.z))
{
yr1->push_back(p0);
distances = distances + euclideanDistance(point56, p0);
point56 = p0;
}
//判断寻找的终点,当遇到叶节点时,此时点56为在分支上的新节点且加入了路径
for (const auto& point9 : jie->points)
{
float x1 = point9.x;
float y1 = point9.y;
float z1 = point9.z;
if (x1 == point53.x && y1 == point53.y && z1 == point53.z)
{
//如果点53是叶节点,那么56就是分支上的一点,而且已经加入到了路径。此时的边代表的就是分支上第一段的关系
it = resulta.erase(it);
//删除后,最小生成树就没有这两点的对应关系,下次就不会搜索到。但是删除的话就会影响下一次的路径寻找
//下一次在新的路径寻找时就会找不到,所以在
}
}
bool fsa = false;
for (const auto& point93 : yejian->points)
{
float x2 = point93.x;
float y2 = point93.y;
float z2 = point93.z;
if (x2 == point56.x && y2 == point56.y && z2 == point56.z)
{
fsa = true;
break;
}
}
if (fsa != false)
{
break;
}
}
}
begin6++;
for (size_t i = 0; i < yr1->size(); ++i)
{
std::cout << "Point " << i + 1 << " coordinates" << "("
<< yr1->points[i].x << ", "
<< yr1->points[i].y << ", "
<< yr1->points[i].z << ")" << std::endl;
}
cout << " " << endl;
}
//五片路径的指针都已经放在了指针容器clouds1里了,之后调用每片叶子指针时用clouds[i]就可以,而且也方便
}
解决方法:
- 使用
delete释放指针: 在函数结束前,遍历clouds1容器,使用delete关键字释放每个指针指向的内存空间。例如:
for (auto& cloud : clouds1) {
delete cloud;
}
- 使用智能指针: 使用
std::shared_ptr或std::unique_ptr来管理pcl::PointCloud对象的生命周期。智能指针会自动在对象不再使用时释放内存。例如:
std::vector<std::shared_ptr<pcl::PointCloud<pcl::PointXYZRGB>>> clouds1;
for (int i = 0; i < m; ++i) {
clouds1.push_back(std::make_shared<pcl::PointCloud<pcl::PointXYZRGB>>());
}
选择方法:
- 如果代码中没有其他地方需要使用这些
pcl::PointCloud对象,并且在函数结束时释放即可,使用delete释放指针是比较简洁的做法。 - 如果代码中其他地方也需要使用这些对象,或者需要更复杂的内存管理机制,使用智能指针是更好的选择。
注意:
- 使用
delete释放指针时,需要确保指针没有被释放多次。 - 使用智能指针时,需要注意指针的引用计数。
通过使用上述方法,可以避免内存泄漏,提高代码的稳定性和可靠性。
建议:
- 在代码中使用智能指针来管理对象的生命周期,可以简化内存管理,提高代码的可读性和安全性。
- 定期对代码进行内存泄漏检查,可以及时发现并解决问题,避免程序出现崩溃或性能下降。
原文地址: https://www.cveoy.top/t/topic/qAMo 著作权归作者所有。请勿转载和采集!