内存泄漏C++
Memory leak C++
我刚刚用C++写了一段代码,它可以进行一些字符串操作,但当我运行valgrind时,它显示了一些可能的内存泄漏。将代码调试到细粒度级别我写了一个简单的C++程序,看起来像:
#include<iostream>
#include<cstdlib>
using namespace std;
int main()
{
std::string myname("Is there any leaks");
exit(0);
}
我得到了:
==20943== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 26 from 1)
==20943== malloc/free: in use at exit: 360,645 bytes in 12,854 blocks.
==20943== malloc/free: 65,451 allocs, 52,597 frees, 2,186,968 bytes allocated.
==20943== For counts of detected errors, rerun with: -v
==20943== searching for pointers to 12,854 not-freed blocks.
==20943== checked 424,628 bytes.
==20943==
==20943== LEAK SUMMARY:
==20943== definitely lost: 0 bytes in 0 blocks.
==20943== possibly lost: 917 bytes in 6 blocks.
==20943== still reachable: 359,728 bytes in 12,848 blocks.
==20943== suppressed: 0 bytes in 0 blocks.
==20943== Reachable blocks (those to which a pointer was found) are not shown.
==20943== To see them, rerun with: --show-reachable=yes
然后我突然意识到我们已经强制退出(这也是我在原始C++代码中执行的)。现在的问题是,我想退出程序,因为我以前的旧代码正在等待新代码的退出状态。例如二进制a.out等待b.out的退出状态。有什么方法可以避免内存泄漏吗?或者我真的应该担心内存泄漏吗,因为程序已经在退出了。
这也给我提出了另一个问题,这样的代码有害吗?
#include<stdio.h>
#include<cstdlib>
int main()
{
char *p=(char *)malloc(sizeof(char)*1000);
exit(0);
}
在main
末尾使用return 0;
而不是exit(0);
。exit
的使用避免了析构函数的执行。
如果您坚持使用exit()
:
#include<iostream>
int main(){
{
std::string myname("Are there any leaks?");
}
exit(0);
}
此外,当您从main
返回时,返回的值将成为应用程序的退出代码。因此,如果要传递退出代码,请在main()
中使用return exitCode;
,而不是exit
。
关于该部分:
这也给我提出了另一个问题,这样的代码有害吗?
是的,因为这是一个BAD编程习惯。
操作系统会清理你未能释放的任何内存,所以只要你没有吃掉所有系统内存和页面文件,就不应该损坏操作系统。
然而,编写草率/泄漏的代码可能会成为一种习惯,所以依赖操作系统来清理你的烂摊子是个坏主意。
这也给我提出了另一个问题,这样的代码有害吗?
#include<stdio.h> int main() { char *p=(char *)malloc(sizeof(char)*1000); exit(0); }
这对现代操作系统没有害处,因为当进程结束时,它们会自动关闭进程拥有的所有资源。
然而,这仍然是一种糟糕的做法,当经过几年的维护,代码慢慢更改,直到某一天,这确实变得有害时,可能会导致微妙且难以找到的错误。我在一些项目中工作过,其中一些代码已经有十年的历史了,我从中吸取了一些教训,其中一些相当苛刻。因此,我会避免编写这样的代码,即使它目前没有造成问题。
在大多数情况下,它值得自己清理,原因有很多:更好的可维护性,检查工具的实用性更好等等
如果有其他功能原因需要清理,也许你的数据被保存到了一个持久存储中,那么你别无选择——你必须清理(尽管你可能想重新考虑你的设计)。
然而,在某些情况下,最好只是退出并"泄漏"。
在程序结束时,您的进程将退出。当它这样做时,操作系统将恢复程序分配的任何内存,在某些情况下,它可以更快地恢复。
考虑一个大的链表,其中每个节点都是动态分配的,并承载一个实质性的动态分配结构。要清理此问题,您必须访问每个节点并释放每个有效负载(这反过来可能会导致其他复杂结构被遍历)。
您最终可能会执行数百万次内存操作来运行这样的结构。
用户想退出你的程序,他们在那里坐了10秒钟,等待一堆垃圾处理发生。他们不可能对结果感兴趣——毕竟他们要退出这个项目了。
如果让这种"泄漏",操作系统可以更快地回收分配给进程的整个内存块。它不关心结构和任何对象清理。
http://blogs.msdn.com/b/oldnewthing/archive/2012/01/05/10253268.aspx
最终,你必须了解你的工具在告诉你什么,以确保你正确使用了它们。
要避免内存泄漏,请从main
返回状态,而不是调用exit
。如果返回零,如果愿意,可以省略return
语句;在这种情况下,程序将以零状态退出。
这也给我提出了另一个问题,这样的代码有害吗?
在现代操作系统上,它不会造成任何伤害——当程序终止时,所有资源都会自动回收。然而,这确实使使用Valgrind等工具更难发现真正的问题,因此,如果可以的话,最好避免无害的内存泄漏。
#include<iostream>
using namespace std;
int main()
{
{
std::string myname("Is there any leaks");
}
exit(0);
}
在进程实际退出时,就像main()退出时一样,操作系统将以任何方式回收分配给应用程序的所有资源。如何退出并不那么重要——至少在动态内存方面是如此。
如果你打开了一些分布式数据库连接或其他什么,你应该使用atexit()处理程序来关闭它,而直接退出的强制终止可能会使它们无法运行,这会很糟糕——但就你的操作系统资源而言,你可能还可以。
您还应该始终确保释放(手动)文件锁和类似的东西,因为它们可能不会因为进程退出而消失。
如果您想在不超过析构函数的情况下中断执行并传递返回代码,请抛出异常,并从main()
中的异常中提取返回值。
如果程序正在退出,您不必担心分配给malloc
或new
的内存。操作系统会处理它——当进程死亡时,进程虚拟地址空间中的任何东西都会消失。如果您使用的是共享内存或命名管道,这可能仍然是一个问题。
添加不同的意见。
这样的代码并没有什么害处。当进程终止时,操作系统将处理所有事务。其他一切都会导致操作系统不稳定。只需确保您的持久数据(文件,…)是一致的。
更进一步,挑衅性的状态,在程序退出时显式释放内存可能是有害的。
- 程序退出需要更长的时间(你有没有因为等待程序退出直到计算机关闭而感到恼火?)
- 正确的销毁顺序并不总是微不足道的,尤其是对于第三方组件(我记得一些程序可能在退出时崩溃)
- 操作系统可能不允许您在离开
main
(*)后释放内存,而是终止您的程序
你冒这个风险只是为了让Valgrind给你一个特定的输出吗?(**)
(*)
#include<iostream>
using namespace std;
std::string myname("Is there any leaks");
int main() {
exit(0);
}
(**)当然,任何内存分析器的输出在没有"噪音"的情况下都更有用。在调试模式下,只在退出时显式释放内存怎么样?
- valgrind-hellgrind与泄漏检查的结果不同
- 从构造函数抛出异常时如何克服内存泄漏
- malloc() 可能出现内存泄漏
- 这个极客对极客的trie实现是否存在内存泄漏问题
- 尽管遵循了规则,内存泄漏在哪里
- 为什么调用堆栈数组会导致内存泄漏
- 在简单示例中,Python3 + ctypes 回调会导致内存泄漏
- 使用模板类的自定义列表类型中的内存泄漏
- 为什么以下C++代码中存在内存泄漏?
- Klocwork Inside的资源泄漏
- OpenCV 我应该使用智能指针来防止内存泄漏吗?
- 我是否生成线程并导致内存泄漏?
- 多线程程序中出现意外的内存泄漏
- 为什么此函数会导致内存泄漏?
- 在 C++ 库中使用cythonized python时内存泄漏
- 需要帮助查找内存泄漏
- C++功能泄漏内存,我是C++新手,不确定如何解决
- 瓦尔格林德的内存泄漏使用新的
- CPP 中的瓦尔格林德和记忆泄漏:"Conditional jump or move depends on uninitialised values"
- 无法找出我的代码中的内存泄漏