C++ 在不释放所有动态分配的资源的情况下结束程序是否有风险?
我知道堆栈分配的资源是以相反的顺序释放的,因为它们是作为RAII的一部分在函数末尾分配的。我一直在做一个项目,我用我正在使用的库中的“new”分配了大量内存,并且正在测试这些东西。我还没有添加一个shutdown函数作为initialise函数的对应项,initialise函数执行所有的动态分配。当你关闭程序时,我很确定没有内存泄漏,因为分配的内存应该由操作系统回收。至少任何现代操作系统,正如在这个问题中解释的,与我的类似: 我想知道两件事: 1:在这种情况下,是否有特定的资源释放顺序?它是否与您编写的代码有关(即,您分配代码的顺序),还是完全由操作系统来完成 2:我没有做一个关闭函数来反转初始化的原因是因为我对自己说,我现在只是在测试东西,以后再做。做我正在做的事会有任何损害任何东西的风险吗?我能想象的最糟糕的情况是在我链接的问题的答案中提到的,即操作系统无法回收内存,即使在程序退出后,也会导致内存泄漏 我遵循Bullet physics library教程,初始化了一系列代码,如下所示:C++ 在不释放所有动态分配的资源的情况下结束程序是否有风险?,c++,heap-memory,dynamic-allocation,C++,Heap Memory,Dynamic Allocation,我知道堆栈分配的资源是以相反的顺序释放的,因为它们是作为RAII的一部分在函数末尾分配的。我一直在做一个项目,我用我正在使用的库中的“new”分配了大量内存,并且正在测试这些东西。我还没有添加一个shutdown函数作为initialise函数的对应项,initialise函数执行所有的动态分配。当你关闭程序时,我很确定没有内存泄漏,因为分配的内存应该由操作系统回收。至少任何现代操作系统,正如在这个问题中解释的,与我的类似: 我想知道两件事: 1:在这种情况下,是否有特定的资源释放顺序?它是否与
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);