【发布时间】:2017-04-04 14:36:35
【问题描述】:
我是 C++ 编码和 STL 库使用的新手。我对在我正在开发的 C++ 程序上使用 STL 库非常感兴趣。但最近我尝试使用 Visual Leak 检测器,发现很多泄漏,特别是我使用 STL 库和 new 运算符的地方。
由于它是一个运行时应用程序,我还发现当我连续运行代码 4-5 天时 CPU 内存不断增加。在一些论坛和其他注意到的学习中,我了解到我需要删除/擦除std::map、std::unordered_map、std:set 中的内容,然后再调用其对应的clear。
我的问题是,如果我在永远不会调用的析构函数调用上执行所有这些操作(因为我的程序员永远不会停止),STL 库是否会在我每次访问它时造成内存泄漏?
有没有替代方案?
例如:common.h
struct stTagElem_t {
uint32_t m_unOffset;
uint32_t m_unArraySize;
string m_acTagName;
string m_acTagValue;
string m_acDataType;
} ;
typedef std::unordered_map<uint8_t, stTagElem_t> tagsList_t;
struct stMappingElem_t {
uint16_t m_unMemSize;
tagsList_t m_stTagsList;
string m_acEventName;
string m_acMapTypeName;
} ;
typedef std::unordered_map<uint32_t, stMappingElem_t> eventDataMap_t;
dataMapManager.cpp //声明为全局列表,因为dataMapManager.cpp拥有所有静态函数
eventDataMap_t sm_eventDataMapList;
所以当我使用 Visual Leak Detector 时,它会显示以下内容:
---------- Block 596 at 0x00DE8DB8: 120 bytes ----------
Leak Hash: 0xB26C3A34, Count: 1, Total 120 bytes
Call Stack (TID 11580):
c:\program files (x86)\microsoft visual studio 14.0\vc\include\xmemory0 (977): example.exe!std::_Wrap_alloc<std::allocator<std::_List_node<std::pair<unsigned __int64 const ,stMappingElem_t>,void *> > >::allocate()
c:\program files (x86)\microsoft visual studio 14.0\vc\include\list (730): example.exe!std::_List_alloc<std::_List_base_types<std::pair<unsigned __int64 const ,stMappingElem_t>,std::allocator<std::pair<unsigned __int64 const ,stMappingElem_t> > > >::_Buynode0() + 0x11 bytes
c:\program files (x86)\microsoft visual studio 14.0\vc\include\list (716): example.exe!std::_List_alloc<std::_List_base_types<std::pair<unsigned __int64 const ,stMappingElem_t>,std::allocator<std::pair<unsigned __int64 const ,stMappingElem_t> > > >::_Buyheadnode()
c:\program files (x86)\microsoft visual studio 14.0\vc\include\list (649): example.exe!std::_List_alloc<std::_List_base_types<std::pair<unsigned __int64 const ,stMappingElem_t>,std::allocator<std::pair<unsigned __int64 const ,stMappingElem_t> > > >::_List_alloc<std::_List_base_types<std::pair<unsigned __int64 const ,stMappingElem_t>,std::al() + 0x8 bytes
c:\program files (x86)\microsoft visual studio 14.0\vc\include\list (826): example.exe!std::_List_buy<std::pair<unsigned __int64 const ,stMappingElem_t>,std::allocator<std::pair<unsigned __int64 const ,stMappingElem_t> > >::_List_buy<std::pair<unsigned __int64 const ,stMappingElem_t>,std::allocator<std::pair<unsigned __int64 const ,stMappin()
c:\program files (x86)\microsoft visual studio 14.0\vc\include\list (899): example.exe!std::list<std::pair<unsigned __int64 const ,stMappingElem_t>,std::allocator<std::pair<unsigned __int64 const ,stMappingElem_t> > >::list<std::pair<unsigned __int64 const ,stMappingElem_t>,std::allocator<std::pair<unsigned __int64 const ,stMappingElem_t> >()
c:\program files (x86)\microsoft visual studio 14.0\vc\include\xhash (197): example.exe!std::_Hash<std::_Umap_traits<unsigned __int64,stMappingElem_t,std::_Uhash_compare<unsigned __int64,std::hash<unsigned __int64>,std::equal_to<unsigned __int64> >,std::allocator<std::pair<unsigned __int64 const ,stMappingElem_t> >,0> >::_Hash<std::_Umap_tra() + 0xF bytes
c:\program files (x86)\microsoft visual studio 14.0\vc\include\unordered_map (119): example.exe!std::unordered_map<unsigned __int64,stMappingElem_t,std::hash<unsigned __int64>,std::equal_to<unsigned __int64>,std::allocator<std::pair<unsigned __int64 const ,stMappingElem_t> > >::unordered_map<unsigned __int64,stMappingElem_t,std::hash<unsigned __int6()
g:\mywork\src\datamapmanager.cpp (15): example.exe!`dynamic initializer for 'sm_eventDataMapList''() + 0xD bytes
d:\rs1\minkernel\crts\ucrt\src\appcrt\startup\initterm.cpp (22): ucrtbased.dll!_initterm()
f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl (221): example.exe!__scrt_common_main_seh() + 0xF bytes
f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl (296): example.exe!__scrt_common_main()
f:\dd\vctools\crt\vcstartup\src\startup\exe_main.cpp (17): example.exe!mainCRTStartup()
KERNEL32.DLL!BaseThreadInitThunk() + 0x24 bytes
ntdll.dll!__RtlUserThreadStart() + 0x2F bytes
ntdll.dll!_RtlUserThreadStart() + 0x1B bytes
Data:
38 09 E6 00 F0 98 E8 00 CD CD CD CD CD CD CD CD 8....... ........
CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........
CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........
CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........
CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........
CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........
CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........
CD CD CD CD CD CD CD CD ........ ........
更多地图:common.h
using namespace std;
#ifdef USE_64BIT
typedef uint64_t ID;
#else
typedef uint32_t ID;
#endif
typedef ID EVENT_UID;
struct stEventParams_t {
EVENT_UID m_unEventID;
uint8_t *m_ptrMemAddr;
size_t m_dataSize;
} ;
struct stTagElem_t {
uint32_t m_unOffset;
uint32_t m_unArraySize;
string m_acTagName;
string m_acTagValue;
string m_acDataType;
} ;
typedef std::unordered_map<uint8_t, stTagElem_t> tagsList_t;
struct stMappingElem_t {
uint16_t m_unMemSize;
tagsList_t m_stTagsList;
string m_acEventName;
string m_acMapTypeName;
} ;
typedef std::unordered_map<EVENT_UID, stMappingElem_t> eventDataMap_t;
struct stAppBlocInfo_t {
string m_acAppBlocName;
string m_acInstanceName;
string m_acDataMap_r_SPError;
string m_acTypeName;
} ;
typedef std::unordered_map<string, string> instanceTypeList_t;
typedef struct {
stAppBlocInfo_t m_acServiceProvider;
instanceTypeList_t m_acParamsList;
} stSP_Params_t;
typedef std::unordered_map<string, stSP_Params_t> serviceProvider_t;
struct stServiceParams_t {
bool m_bIsItOutput;
uint8_t m_unIdxToEvtClient;
EVENT_UID m_unEventID;
string m_acInstanceName;
string m_acTypeName;
instanceTypeList_t m_acParamsList;
} ;
typedef std::unordered_map<ID, stServiceParams_t> serviceParams_t;
struct stStatusElem_t {
bool m_bErrorPresent;
std::string m_acSPError;
instanceTypeList_t m_ServiceStatus;
};
typedef std::unordered_map<CSI_base *, stSP_Params_t > spInstanceList_t;
typedef CSI_base* (*CREATE_SI)(stSP_Params_t, eventDataMap_t, serviceParams_t);
typedef std::map<std::string, HINSTANCE> extnSiObjList_t;
struct AppBloc_Elements {
APPBLOCNAME m_acAppBlocName;
CFBNwExecutor *ptrFbnExec;
};
typedef std::map<APPLET_ID, AppBloc_Elements> AppBlocElemList;
typedef std::map<APPBLOCNAME, APPLET_ID> AppBlocsList;
如果我在大多数用例中使用标准 STL 库,我的整个应用程序包含 50 多个 cpp 文件。
【问题讨论】:
-
“特别是在我使用 STL 库和
new运算符的地方”——这是你的问题,不需要使用new为 STL 容器实例分配空间。 -
不再有 STL 这样的东西,而不是您使用该术语的方式。它都被称为“标准库”。
-
在清除它们之前不需要从标准容器中删除元素,除非它们包含拥有原始指针或其他原始拥有句柄。
tagsList_t和eventDataMap_t没有任何原始拥有指针,您不必担心这些类型的容器泄漏。 -
您显示的代码中没有任何内容看起来像内存泄漏。如果您有,则需要提供minimal reproducible example 以获得帮助。
标签: c++ c++11 memory memory-leaks stl