当我创建一个空控制台应用程序并在其中使用STL容器时,FastMM在应用程序关闭时报告内存泄漏。
例如,如果我在main()
中创建一个std::vector<int>
:
std::vector<int> v;
编译,运行并关闭,无泄漏报告。
如果我这样做:
std::vector<int> v;
v.push_back(100);
我:
类似地,我得到一个泄漏报告:应用程序内存泄漏。小块泄漏为:
309 - 340 bytes: Unknown x 1
std::vector<int> v;
v.push_back(100);
v.clear();
还有一个泄漏报告:
std::vector<int> v;
v.reserve(1);
对于一些容器,比如std::deque
,仅仅创建一个容器就足够了,即使不改变其内容,当应用程序关闭时也会报告泄漏。
FastMMOptions.inc
的各种设置,但我仍然看到这些泄漏报告。
清除std::vector
不会释放用于vector
内部数组的内存,它只是销毁数组内的项,然后将std::vector::size()
设置为0。数组本身仍然是分配的,所以它可以重新用于在vector
中推入的新项。vector
的析构函数将释放该数组。
在c++ Builder 6中,默认的STL库是STLPort(在c++ Builder 2006中被Dinkumware取代)。STLPort对~std::vector()
的实现仅仅销毁了数组项(就像调用了clear()
一样),但没有释放数组本身,因此出现了您所看到的"泄漏"。根据STLPort网站上的以下常见问题解答,这实际上根本不是泄漏:
Q6.2我的工具检测内存泄漏与STLport应用程序。这是从STLport泄露的吗?
在大多数情况下,这是一些工具错误支持的"伪内存泄漏"。在STLport的默认编译中,使用节点分配器分配内部内存。节点分配器通过预先分配大块内存并分发小内存块来工作。内存块在运行使用STLport的应用程序期间不释放(即它不返回到系统,有像BoundsChecker, Purify或Valgrind这样的工具来检查内存泄漏,当不再使用时不释放的内存。当使用st_port的节点分配器时,这些工具可能会报告错误的内存泄漏。内存块通常在应用程序结束时释放,但内存检查器通常在该点之前报告内存泄漏。当您使用共享库(例如DLL,此问题特定于Windows DLL模型)内部使用STLport并静态链接到它时,可能会报告另一个内存问题。如果内存在一个dll中分配,而在另一个dll中释放,那么STLport节点分配器将保留释放的内存以备将来使用。如果不使用此内存,那么即使没有真正的内存泄漏,应用程序的全局内存消耗也会增长,直到应用程序崩溃。这就是为什么你应该始终使用一致的配置,所有的东西都在dll中,或者所有的东西都在静态库中。
有一些方法可以消除伪内存泄漏(因为内存在程序结束时被正确释放,所以泄漏只是伪内存泄漏)。您可以使用STLport中使用的另一个分配器。打开文件"stlport/stl/_site_config.h"
并取消以下注释之一:_STLP_USE_NEWALLOC enables a simple allocator that uses "new/delete" _STLP_USE_MALLOC enables a simple allocator that uses "malloc/free"
新的/delete分配器的优点是提供了一个跟踪内存耗尽的入口点,有关更多信息,请参阅编译器文档或c++标准中的set_new_handler。
或者您可以定义以下符号,只需在
"stlport/stl/_site_config.h"
中取消注释即可。_STLP_LEAKS_PEDANTIC
符号强制释放所有内存块。也可以查看配置文件中符号周围的注释。
请注意,如果对文件进行任何更改,您必须重新编译STLport和您的应用程序以及所有依赖的库!
还有一些定义可以帮助调试STLport中的内存问题。在_STLP_DEBUG模式下,只需在"./stlport/stl_user_config.h"或项目设置中定义以下符号:
_STLP_DEBUG_ALLOC _STLP_DEBUG_UNINITIALIZED
您不需要为这些选项重新构建STLport,但是如果您对文件进行任何更改,则必须重新构建应用程序和所有依赖库。
也就是说,在早期的c++ Builder版本中使用的RogueWave STL也随c++ Builder 6一起发布,以向后兼容旧代码,并且不会受到此问题的影响。你可以通过在项目的条件列表中定义_USE_OLD_RW_STL
从STLPort切换到RogueWave。