C ++是否有必要在主范围的末尾删除动态分配的对象?

时间:2021-06-11 21:20:30

When using dynamically allocated objects in C++ eg:

在C ++中使用动态分配的对象时,例如:

TGraph* A = new TGraph(...);

One should always delete these because otherwise the objects might still be in memory when control is handed back to the parent scope. While I can see why this is true for subscopes and subroutines of a program, does the same count for the main scope?

应该总是删除这些,因为否则当控制权交还给父范围时,对象可能仍然在内存中。虽然我可以看到为什么对于程序的子范围和子程序来说这是正确的,但主要范围的计数是否相同?

Am I obliged to delete objects that were dynamically built inside main()? The reason why this seems a bit redudant to me is that when main ends, the program also ends, so there is no need to worry about memory leaks.

我是否有义务删除在main()中动态构建的对象?这对我来说似乎有点减少的原因是,当主要结束时,程序也会结束,所以不必担心内存泄漏。

7 个解决方案

#1


9  

Most of the modern OS always reclaim back all memory they allocated to a program(process).
The OS doesn't really understand if your program leaked memory it merely takes back what it allocatted.

大多数现代操作系统总是回收它们分配给程序(进程)的所有内存。操作系统并不真正了解您的程序是否泄漏了内存,它只会收回它分配的内容。

But there are bigger issues at hand than just the memory loss:

但是手头上存在的问题不仅仅是记忆丧失:

Note that if the destructor of the object whos delete needs to be called performs some non-trivial operation and your program depends on the side effects produced by it then your program falls prey to Undefined Behavior[Ref 1]. Once that happens all bets are off and your program may show any beahvior.

请注意,如果需要调用删除的对象的析构函数执行一些非平凡的操作,并且您的程序依赖于它产生的副作用,那么您的程序将成为Undefined Behavior [Ref 1]的牺牲品。一旦发生这种情况,所有投注都会被取消,您的计划可能会显示任何行为。

Also, An OS usually reclaims the allocated memory but not the other resources, So you might leak those resources indirectly. This may include operations dealing with file descriptors or state of the program itself etc.

此外,操作系统通常会回收已分配的内存而不回收其他资源,因此您可能会间接泄漏这些资源。这可能包括处理文件描述符的操作或程序本身的状态等。

Hence, it is a good practice to always deallocate all your allocations by calling delete or delete [] before exiting your program.

因此,最好在退出程序之前通过调用delete或delete []来释放所有分配。


[Ref 1]C++03 Standard 3.8 Para 4:

[参考1] C ++ 03标准3.8第4段:

"....if there is no explicit call to the destructor or if a delete-expression (5.3.5) is not used to release the storage, the destructor shall not be implicitly called and any program that depends on the side effects produced by the destructor has undefined behavior."

“....如果没有对析构函数的显式调用或者如果没有使用delete-expression(5.3.5)来释放存储,则不应该隐式调用析构函数,并且任何依赖于生成的副作用的程序都会生成析构函数具有未定义的行为。“

#2


7  

IMO it is best to always call delete properly:

IMO最好始终正确调用delete:

  • to make it an automatic habit, making it less likely to forget it when it is really needed
  • 使其成为一种自动习惯,使其在真正需要时不太可能忘记它

  • to cover cases when non-memory resources (sockets, file handles, ...) need to be freed - these aren't automatically freed by the OS
  • 覆盖需要释放非内存资源(套接字,文件句柄,...)的情况 - 这些不会被操作系统自动释放

  • to cater for future refactoring when the code in question might be moved out of main scope
  • 当有问题的代码可能被移出主要范围时,以迎合将来的重构

#3


3  

Yes, you should call delete, at least because it's best practice. If you have important logic in your destructor, that's one extra reason that you should call delete.

是的,您应该致电删除,至少是因为这是最佳做法。如果你的析构函数中有重要的逻辑,那么你应该调用delete的另一个原因。

Corrected: If the program depends on logic in the destructor, not calling delete explicitly results in undefined behavior.

更正:如果程序依赖于析构函数中的逻辑,则不显式调用delete会导致未定义的行为。

#4


0  

The reason why this seems a bit redudant to me is that when main ends, the program also ends, so there is no need to worry about memory leaks.

这对我来说似乎有点减少的原因是,当主要结束时,程序也会结束,所以不必担心内存泄漏。

You're right, but consider this: you create a class object which opens a connection to remote DB. After your program will complete, you should tell the DB "I'm done, i'm going to disconnect", but it won't happen in the case you won't call delete properly.

你是对的,但考虑一下:你创建了一个类对象,它打开了与远程数据库的连接。你的程序完成后,你应该告诉数据库“我已经完成了,我将要断开连接”,但是如果你不能正确地调用delete,就不会发生这种情况。

#5


0  

Its the best practice to de-allocate memory that's been allocated. You should keep in mind that Heap memory is limited and just allocating with out de-allocating while your program is running might run the heap space out for some other/or the same program(if its some kind of a daemon that is meant to run for a very long time) that needs heap.

它是取消分配已分配内存的最佳实践。你应该记住堆内存是有限的,只是在你的程序运行时分配没有解除分配可能会为其他/或同一个程序运行堆空间(如果它的某种守护程序是运行的话)很长一段时间)需要堆。

Of course memory will be reclaimed by the operating system at the end of the program's execution.

当然,在程序执行结束时,操作系统将回收内存。

#6


0  

I see you are using ROOT (CMS guy?). I think ROOT takes care of this and cleans up, doesn't it?

我看到你正在使用ROOT(CMS家伙?)。我认为ROOT会照顾这个并清理,不是吗?

#7


0  

Best practices:

  1. Do not use new, use automatic allocation
  2. 不要使用新的,使用自动分配

  3. When dynamic allocation is necessary, use RAII to ensure automatic cleanup
  4. 当需要动态分配时,使用RAII确保自动清理

You should never have to write delete in applicative code.

您永远不必在应用程序代码中编写删除。

Here, why are you calling new for TGraph ?

在这里,你为什么要为TGraph打电话?

TGraph A(...);

works better: less worries!

效果更好:减少担忧!

#1


9  

Most of the modern OS always reclaim back all memory they allocated to a program(process).
The OS doesn't really understand if your program leaked memory it merely takes back what it allocatted.

大多数现代操作系统总是回收它们分配给程序(进程)的所有内存。操作系统并不真正了解您的程序是否泄漏了内存,它只会收回它分配的内容。

But there are bigger issues at hand than just the memory loss:

但是手头上存在的问题不仅仅是记忆丧失:

Note that if the destructor of the object whos delete needs to be called performs some non-trivial operation and your program depends on the side effects produced by it then your program falls prey to Undefined Behavior[Ref 1]. Once that happens all bets are off and your program may show any beahvior.

请注意,如果需要调用删除的对象的析构函数执行一些非平凡的操作,并且您的程序依赖于它产生的副作用,那么您的程序将成为Undefined Behavior [Ref 1]的牺牲品。一旦发生这种情况,所有投注都会被取消,您的计划可能会显示任何行为。

Also, An OS usually reclaims the allocated memory but not the other resources, So you might leak those resources indirectly. This may include operations dealing with file descriptors or state of the program itself etc.

此外,操作系统通常会回收已分配的内存而不回收其他资源,因此您可能会间接泄漏这些资源。这可能包括处理文件描述符的操作或程序本身的状态等。

Hence, it is a good practice to always deallocate all your allocations by calling delete or delete [] before exiting your program.

因此,最好在退出程序之前通过调用delete或delete []来释放所有分配。


[Ref 1]C++03 Standard 3.8 Para 4:

[参考1] C ++ 03标准3.8第4段:

"....if there is no explicit call to the destructor or if a delete-expression (5.3.5) is not used to release the storage, the destructor shall not be implicitly called and any program that depends on the side effects produced by the destructor has undefined behavior."

“....如果没有对析构函数的显式调用或者如果没有使用delete-expression(5.3.5)来释放存储,则不应该隐式调用析构函数,并且任何依赖于生成的副作用的程序都会生成析构函数具有未定义的行为。“

#2


7  

IMO it is best to always call delete properly:

IMO最好始终正确调用delete:

  • to make it an automatic habit, making it less likely to forget it when it is really needed
  • 使其成为一种自动习惯,使其在真正需要时不太可能忘记它

  • to cover cases when non-memory resources (sockets, file handles, ...) need to be freed - these aren't automatically freed by the OS
  • 覆盖需要释放非内存资源(套接字,文件句柄,...)的情况 - 这些不会被操作系统自动释放

  • to cater for future refactoring when the code in question might be moved out of main scope
  • 当有问题的代码可能被移出主要范围时,以迎合将来的重构

#3


3  

Yes, you should call delete, at least because it's best practice. If you have important logic in your destructor, that's one extra reason that you should call delete.

是的,您应该致电删除,至少是因为这是最佳做法。如果你的析构函数中有重要的逻辑,那么你应该调用delete的另一个原因。

Corrected: If the program depends on logic in the destructor, not calling delete explicitly results in undefined behavior.

更正:如果程序依赖于析构函数中的逻辑,则不显式调用delete会导致未定义的行为。

#4


0  

The reason why this seems a bit redudant to me is that when main ends, the program also ends, so there is no need to worry about memory leaks.

这对我来说似乎有点减少的原因是,当主要结束时,程序也会结束,所以不必担心内存泄漏。

You're right, but consider this: you create a class object which opens a connection to remote DB. After your program will complete, you should tell the DB "I'm done, i'm going to disconnect", but it won't happen in the case you won't call delete properly.

你是对的,但考虑一下:你创建了一个类对象,它打开了与远程数据库的连接。你的程序完成后,你应该告诉数据库“我已经完成了,我将要断开连接”,但是如果你不能正确地调用delete,就不会发生这种情况。

#5


0  

Its the best practice to de-allocate memory that's been allocated. You should keep in mind that Heap memory is limited and just allocating with out de-allocating while your program is running might run the heap space out for some other/or the same program(if its some kind of a daemon that is meant to run for a very long time) that needs heap.

它是取消分配已分配内存的最佳实践。你应该记住堆内存是有限的,只是在你的程序运行时分配没有解除分配可能会为其他/或同一个程序运行堆空间(如果它的某种守护程序是运行的话)很长一段时间)需要堆。

Of course memory will be reclaimed by the operating system at the end of the program's execution.

当然,在程序执行结束时,操作系统将回收内存。

#6


0  

I see you are using ROOT (CMS guy?). I think ROOT takes care of this and cleans up, doesn't it?

我看到你正在使用ROOT(CMS家伙?)。我认为ROOT会照顾这个并清理,不是吗?

#7


0  

Best practices:

  1. Do not use new, use automatic allocation
  2. 不要使用新的,使用自动分配

  3. When dynamic allocation is necessary, use RAII to ensure automatic cleanup
  4. 当需要动态分配时,使用RAII确保自动清理

You should never have to write delete in applicative code.

您永远不必在应用程序代码中编写删除。

Here, why are you calling new for TGraph ?

在这里,你为什么要为TGraph打电话?

TGraph A(...);

works better: less worries!

效果更好:减少担忧!