2016-07-05 68 views
0

当我创建一个空的控制台应用程序并在其中使用STL容器时,FastMM在应用程序关闭时报告内存泄漏。FastMM在C++ Builder 6中报告STL容器上的内存泄漏

例如,如果我创建了一个std::vector<int>main()

std::vector<int> v; 

编译,运行和关闭,无泄漏报告。

如果我做的:

std::vector<int> v; 
v.push_back(100); 

我得到:

此应用程序已泄漏的内存。小块泄漏是:

309 - 340字节:未知X 1

类似地,得到了一个泄漏报告:

std::vector<int> v; 
v.push_back(100); 
v.clear(); 

,并且也是泄漏报告:

std::vector<int> v; 
v.reserve(1); 

对于一些容器,如std::deque,它足以创建一个,甚至不改变其内容泄漏是代表当应用程序关闭时orted。

任何人都可以解释发生了什么?我使用Borland C++ Builder 6和FastMM4。我一直在更改FastMMOptions.inc中的各种设置,但是我仍然看到这些泄漏报告。

+3

[Borland C++ Builder 6](https://en.wikipedia.org/wiki/C%2B%2BBuilder#Version_history)似乎在2002年出现了....任何机会,你可以使用更多现代编译器?即使是最新版本的C++ Builder?用软件来说,14年已经很长时间了。 – CoryKramer

+0

我这样说,因为给定的代码片段,没有什么会导致内存泄漏(没有看到周围的上下文),除了由编译器错误的“std :: vector”实现。或泄漏检测器报告的误报。 – CoryKramer

+0

是的,我们有Borland XE7,新项目在新环境中开发。不过,我需要调查现有项目中的内存泄漏,由于它们的大小,我们还没有迁移到XE7。我发现FastMM非常有用,但是因为STL在我们代码的很多地方都有使用,所以它指出了非常让我困惑的泄漏。 – bboydushko

回答

1

清除std::vector不释放用于vector的内部阵列的存储器,它仅仅自毁阵列里面的物品,然后设置std::vector::size()为0的阵列本身仍被分配,因此它可以用于新的被重复使用物品推入vectorvector的析构函数将释放数组。

在C++ Builder 6中,默认的STL库是STLPort(在C++ Builder 2006中用Dinkumware取代)。 STLPort的~std::vector()的实现只是破坏数组项(就好像调用了clear()),但不会释放数组本身,因此您看到的“泄漏”。这实际上不是一个泄漏可言,根据STLPort的网站上的以下FAQ:

Q6.2 My tool detect memory leaks in application with STLport. Is this leak from STLport?

A6.2在大多数情况下,这是“伪内存泄漏”,一些错误的工具支持。

在STLport的默认编译中,节点分配器用于分配内部内存。节点分配器通过预分配一大块内存并分配小内存块来工作。内存块在运行使用STLport的应用程序时不会被释放(即它不会返回到系统,有些工具如BoundsChecker,Purify或Valgrind用于检查memorytml泄漏,对于不再使用时未释放的内存。当使用STLport的节点分配器时,这些工具可能会报告错误的内存泄漏。内存块通常在应用程序结束时释放,但内存检查器通常会在该点之前报告内存泄漏。当您使用内部使用STLport并静态链接到它的共享库时(例如DLL,此问题特定于Windows 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" 

新/删除分配器具有赋予切入点,以跟踪内存饥饿,看到你的编译器的文档或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。

+0

优秀且信息丰富的答复。定义'_USE_OLD_RW_STL'时,FastMM不报告我们项目中使用的容器('std :: vector''std :: list''std :: deque')的任何泄漏。非常感谢你。现在通过内存泄漏报告要容易得多。 – bboydushko

+0

我注意到另一件事情,任何'std :: cout'的用法都会报告泄漏。幸运的是,我们的代码并不多,但是如果您知道另一个'魔术条件定义'来阻止那些出现在报告中的那些会很棒。示例:'std :: cout <<“hello”<< endl;'报告: 13 - 20字节:未知x 1 21 - 36字节:std :: codecvt x 1 ,未知x 2 37 - 52字节:未知x 2 53 - 68字节:std :: ctype x 1,__rwstd :: locale_imp x 2 85 - 100字节:未知x 2 485 - 532字节:未知x 3 ,而'printf(“hello \ n”);'报告没有泄漏 – bboydushko