C++ 在不释放所有动态分配的资源的情况下结束程序是否有风险?

C++ 在不释放所有动态分配的资源的情况下结束程序是否有风险?,c++,heap-memory,dynamic-allocation,C++,Heap Memory,Dynamic Allocation,我知道堆栈分配的资源是以相反的顺序释放的,因为它们是作为RAII的一部分在函数末尾分配的。我一直在做一个项目,我用我正在使用的库中的“new”分配了大量内存,并且正在测试这些东西。我还没有添加一个shutdown函数作为initialise函数的对应项,initialise函数执行所有的动态分配。当你关闭程序时,我很确定没有内存泄漏,因为分配的内存应该由操作系统回收。至少任何现代操作系统,正如在这个问题中解释的,与我的类似: 我想知道两件事: 1:在这种情况下,是否有特定的资源释放顺序?它是否与

我知道堆栈分配的资源是以相反的顺序释放的,因为它们是作为RAII的一部分在函数末尾分配的。我一直在做一个项目,我用我正在使用的库中的“new”分配了大量内存,并且正在测试这些东西。我还没有添加一个shutdown函数作为initialise函数的对应项,initialise函数执行所有的动态分配。当你关闭程序时,我很确定没有内存泄漏,因为分配的内存应该由操作系统回收。至少任何现代操作系统,正如在这个问题中解释的,与我的类似:

我想知道两件事:

1:在这种情况下,是否有特定的资源释放顺序?它是否与您编写的代码有关(即,您分配代码的顺序),还是完全由操作系统来完成

2:我没有做一个关闭函数来反转初始化的原因是因为我对自己说,我现在只是在测试东西,以后再做。做我正在做的事会有任何损害任何东西的风险吗?我能想象的最糟糕的情况是在我链接的问题的答案中提到的,即操作系统无法回收内存,即使在程序退出后,也会导致内存泄漏

我遵循Bullet physics library教程,初始化了一系列代码,如下所示:

pSolver = new btSequentialImpulseConstraintSolver;
pOverlappingPairCache = new btDbvtBroadphase();
pCollisionConfig = new btDefaultCollisionConfiguration();
pDispatcher = new btCollisionDispatcher(pCollisionConfig);
pDynamicsWorld = new btDiscreteDynamicsWorld(pDispatcher, pOverlappingPairCache, pSolver, pCollisionConfig);

现在不要调用delete,因为正如我所说,我只是在测试。

这取决于资源。打开的文件将被关闭。内存将被释放。不会调用析构函数。创建的临时文件将不会被删除


程序退出后没有内存泄漏的风险。

这取决于资源。打开的文件将被关闭。内存将被释放。不会调用析构函数。创建的临时文件将不会被删除


程序退出后不存在内存泄漏的风险。

由于程序可能会崩溃,因此有许多机制可以防止进程停止后发生泄漏,泄漏通常不会那么严重

事实上,如果在程序结束前没有删除很多分配,那么在程序结束后清理内核会更快

但是,析构函数不会运行。这主要导致不删除临时文件。 此外,它还使调试实际内存泄漏变得更加困难


我建议首先使用,不要泄漏。

因为程序可能会崩溃,所以有很多机制可以防止进程停止后泄漏,泄漏通常不会那么糟糕

事实上,如果在程序结束前没有删除很多分配,那么在程序结束后清理内核会更快

但是,析构函数不会运行。这主要导致不删除临时文件。 此外,它还使调试实际内存泄漏变得更加困难


我建议首先使用,不要泄漏。

这取决于内存的实际分配方式和主机系统

如果您只使用不重写
operator new()
的类,并且您使用的现代操作系统保证在进程退出时释放内存资源,那么当程序终止时,应释放所有动态分配的内存。无法保证内存释放的顺序(例如,对象不会以其构造的相同顺序或相反顺序释放)。在这种情况下,唯一真正的风险与主机操作系统中导致程序/进程资源管理不当的错误有关(对于现代windows或unix操作系统中的用户程序来说,这是一种低风险,但不是零风险)

如果您使用的任何类覆盖了
操作符new()
(即在动态构建对象的过程中更改原始内存的分配方式),那么风险取决于实际分配内存的方式,以及释放内存的要求。例如,如果
操作符new()
使用全局或系统范围的资源(例如,互斥锁、信号量、进程间共享的内存),则存在程序无法正确释放这些资源的风险,进而间接导致使用相同资源的其他程序出现问题。实际上,根据此类的设计,所需的清理可能在析构函数、
运算符delete()
或两者的某种组合中-但是,无论如何完成,程序都需要显式释放此类对象(例如,与
表达式相对应的
delete
表达式)确保全球资源得到适当释放

一个风险是不会调用动态分配对象的析构函数。如果程序依赖析构函数执行除释放动态分配的内存(可能由类构造函数分配并由其他成员函数管理)以外的任何操作,则不会执行额外的清理操作

如果您的程序将在没有现代操作系统的主机系统上构建和运行,那么无法保证动态分配的内存将被回收


如果程序中的代码将在较大的长期运行程序中重复使用(例如,重命名
main()
函数,然后从循环中的另一个程序调用),则您的代码可能会导致较大的程序出现内存泄漏。

这取决于内存的实际分配方式和主机系统

如果您只使用不重写
operator new()
的类,并且您使用的是现代操作系统,该系统保证在进程退出时释放内存资源,那么所有这些类都是动态分配的
#include <memory>

// ...

// Allocate everything else with 'new' here, as usual.
// ...

// Except for this one, which doesn't seem to be passed to another
// constructor.      
auto pDynamicsWorld = std::make_unique<btDiscreteDynamicsWorld>(
    pDispatcher, pOverlappingPairCache, pSolver, pCollisionConfig);