在我用C和C ++编写的程序中,我将新建一个对象来完成任务,然后删除该对象。
在新对象之后但在删除对象之前,如果用户按 ctrl + c 来中断该过程,则会导致删除不被调用发生内存泄漏。
我应该怎样做以避免这种情况?
此外,如果操作系统回收了内存,那么打开的文件呢?它们是由操作系统关闭还是我应该手动关闭它们?
答案 0 :(得分:7)
在基于虚拟内存的系统中,无论是否在应用程序代码中明确释放进程,都会在进程终止时将所有内存返回给操作系统。但是,对于其他资源而言,情况可能并非如此,您可能希望干净利落。在这种情况下,您需要为SIGINT
信号(在Ctrl + C上接收)提供自定义信号处理程序,例如, http://linux.die.net/man/2/sigaction
答案 1 :(得分:7)
按 Ctrl C 会向进程发送SIGINT
,默认情况下会大致有序关闭,包括拆除内存管理器并释放所有分配的堆和堆栈。如果您需要执行其他任务,则需要安装SIGINT
处理程序并自行执行这些任务。
答案 2 :(得分:3)
如果您使用shmget(2)
分配了任何SYSV共享内存段,则必须使用shmctl(2)
自行清理。
如果您使用shm_open(3)
分配了任何POSIX共享内存段,则必须使用shm_unlink(3)
自行清理。
SYSV和POSIX共享内存段在进程终止后仍然存在。您可以使用ipcs(1)
工具查看持续存在的内容。
当然,如果你没有使用任何SYSV或POSIX共享内存段,那么这只是噪音。 :)
答案 3 :(得分:2)
当在Linux控制台中按下CTRL + C时,SIGINT信号被发送到应用程序,如果信号没有处理程序,则将终止程序,将所有内存返回给OS。这当然会使得释放内存毫无意义,因为一旦程序存在,所有内存都将被释放。但是,如果您想处理CTRL + C SIGINT信号(可能将最后一些数据写入文件或进行其他清理),您可以使用函数signal()
来安装要调用的函数。收到信号。如果您想了解更多信息,请查看此功能的手册页。
答案 4 :(得分:2)
如果进程退出,通常不会发生内存泄漏。
您分配的大部分内存将在Ctrl + C上释放。如果您发现内存使用率没有恢复到先前的水平,则几乎可以肯定是由缓冲的文件系统块引起的。
但是,你应该清理一下,特别是如果你使用过任何其他类型的资源:
通常,如果后续运行不泄漏更多内存,则(持久性或半持久性对象(例如文件)的泄漏无关紧要)。因此,清理未来的运行就足够了。
想象一下从“cron”开始每隔5分钟运行一个进程,如果它在每次运行时崩溃并且留下一些混乱,那么只要每次运行都能清除前一次崩溃中的混乱,它仍然可以。
答案 5 :(得分:1)
当进程因Ctrl-C或任何其他方式退出时,操作系统将回收进程分配的内存。
答案 6 :(得分:1)
您正在订阅一个相当普遍的误解,即未被释放但在程序存在时仍可访问的堆块是泄漏。这不是真的。泄漏的块是没有指针仍然引用的块,因此它们不能被释放。
通过多年来使用(并且打破)许多非常好的内核,我从未设法将虚拟内存管理器充分破坏到一旦它退出就不再回收进程的整个地址空间的程度。除非您正在使用明确标记为“新实验”的内核,否则您将获得更好的运气赢得彩票,而不是找到不使用有效虚拟内存管理器的系统。
为了在Valgrind获得满分,不要在你的代码中加入。如果您没有真正的清理任务来执行其他而不是释放仍有有效参考的内存,则无需费心。如果有人向您的程序抛出kill -9
,您将无法处理它,并会看到旧的行为重复。
如果你有要清理的文件描述符,要放弃的共享锁,要刷新的流或其他任何必须发生的事情,以便其他进程在你离开时不会错过你,一定要注意这一点。只是不要添加无法解决非问题的代码,这样做似乎很愚蠢。
注意强>
这本来是一个评论,但是太久了,所以一次写一篇小说的评论就不那么沮丧了。