CTypedPtrArray & CStringArray
-
Can you tell me if I use in corect way these classes , CTypedPtrArray & CStringArray ? These are member variable to CMyDoc class :
typedef CTypedPtrArray<CObArray,CStringArray*> CTableArray;
class CMyDoc : public CDocument
{
// Attributes
public:
CStringArray m_saTable;
CTableArray m_saTables;
...
}and here is code snipped for use of them :
m\_saTable.Add("String Test"); m\_saTables.Add(&m\_saTable); CStringArray\* saTest = m\_saTables.GetAt(0); CString sTest = saTest->GetAt(0); TRACE("\\n %s \\n",sTest);
but , where I need to delete elements ? I try to delete items in OnCloseDocument(...)
void CMyDoc::OnCloseDocument()
{
// TODO: Add your specialized code here and/or call the base classm\_saTable.RemoveAll(); m\_saTables.RemoveAll(); TRACE("\\n %d - %d \\n",m\_saTable.GetSize(),m\_saTables.GetSize()); CDocument::OnCloseDocument();
}
But with or without remove code , I didn't have memory leaks in debug window ... is really necesary to delete the items ? Any help , I will appreciated ! Thanks !
-
Can you tell me if I use in corect way these classes , CTypedPtrArray & CStringArray ? These are member variable to CMyDoc class :
typedef CTypedPtrArray<CObArray,CStringArray*> CTableArray;
class CMyDoc : public CDocument
{
// Attributes
public:
CStringArray m_saTable;
CTableArray m_saTables;
...
}and here is code snipped for use of them :
m\_saTable.Add("String Test"); m\_saTables.Add(&m\_saTable); CStringArray\* saTest = m\_saTables.GetAt(0); CString sTest = saTest->GetAt(0); TRACE("\\n %s \\n",sTest);
but , where I need to delete elements ? I try to delete items in OnCloseDocument(...)
void CMyDoc::OnCloseDocument()
{
// TODO: Add your specialized code here and/or call the base classm\_saTable.RemoveAll(); m\_saTables.RemoveAll(); TRACE("\\n %d - %d \\n",m\_saTable.GetSize(),m\_saTables.GetSize()); CDocument::OnCloseDocument();
}
But with or without remove code , I didn't have memory leaks in debug window ... is really necesary to delete the items ? Any help , I will appreciated ! Thanks !
Just one point to offer. Having two member variables named so similarly is likely going to lead to confusion at some later point. Try to come up with names that are more meaningful to the actual use of the data. For example if the strings in the string array class are all people names, cities of the world or street names, try to use that instead of m_saTable. Similarly with the member m_saTables. Just a suggestion. :)
Chris Meech I am Canadian. [heard in a local bar] In theory there is no difference between theory and practice. In practice there is. [Yogi Berra] posting about Crystal Reports here is like discussing gay marriage on a catholic church’s website.[Nishant Sivakumar]
-
Can you tell me if I use in corect way these classes , CTypedPtrArray & CStringArray ? These are member variable to CMyDoc class :
typedef CTypedPtrArray<CObArray,CStringArray*> CTableArray;
class CMyDoc : public CDocument
{
// Attributes
public:
CStringArray m_saTable;
CTableArray m_saTables;
...
}and here is code snipped for use of them :
m\_saTable.Add("String Test"); m\_saTables.Add(&m\_saTable); CStringArray\* saTest = m\_saTables.GetAt(0); CString sTest = saTest->GetAt(0); TRACE("\\n %s \\n",sTest);
but , where I need to delete elements ? I try to delete items in OnCloseDocument(...)
void CMyDoc::OnCloseDocument()
{
// TODO: Add your specialized code here and/or call the base classm\_saTable.RemoveAll(); m\_saTables.RemoveAll(); TRACE("\\n %d - %d \\n",m\_saTable.GetSize(),m\_saTables.GetSize()); CDocument::OnCloseDocument();
}
But with or without remove code , I didn't have memory leaks in debug window ... is really necesary to delete the items ? Any help , I will appreciated ! Thanks !
Firstly, make sure you are dumping the memory leaks correctly. There are a number of ways to do this, but the best is by adding
#if defined(DEBUG) || defined(_DEBUG)
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endifas early in your code as possible, in your case it will be the constructor of your App object
BOOL CxxxApp::CxxxApp()
This is the only way will dump the memory leaks after all static objects have been destroyed. All other ways that I know of will give misleading results if you have static objects If no destructor is provided for your class 1 is generated which calls the destructors of all member classes, otherwise the destructors of all member classes is called after your destructor code. In destructors you only need to delete memory allocated bynew
,malloc
or the likes. Either way, your code is calling the destructors tom_saTable
andm_saTables
and these destructors will free any memory associated with it. Having said that, yourCTableArray
is storing pointers, which means that the destructor for the table will only free the pointers, and not the actual data. You will need to enumerate each item and free its memory manually.CMyDoc::OnCloseDocument()
would be a good place to do this.INT_PTR nElements = m_saTables.GetCount();
for (int nIndex = 0; nIndex < nElements; ++nIndex) {
delete m_saTables.GetAt(nIndex); //assuming the elements inserted were created with "new CStringArray"
} -
Just one point to offer. Having two member variables named so similarly is likely going to lead to confusion at some later point. Try to come up with names that are more meaningful to the actual use of the data. For example if the strings in the string array class are all people names, cities of the world or street names, try to use that instead of m_saTable. Similarly with the member m_saTables. Just a suggestion. :)
Chris Meech I am Canadian. [heard in a local bar] In theory there is no difference between theory and practice. In practice there is. [Yogi Berra] posting about Crystal Reports here is like discussing gay marriage on a catholic church’s website.[Nishant Sivakumar]
Thanks for the suggestion , I will fix that .
-
Firstly, make sure you are dumping the memory leaks correctly. There are a number of ways to do this, but the best is by adding
#if defined(DEBUG) || defined(_DEBUG)
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endifas early in your code as possible, in your case it will be the constructor of your App object
BOOL CxxxApp::CxxxApp()
This is the only way will dump the memory leaks after all static objects have been destroyed. All other ways that I know of will give misleading results if you have static objects If no destructor is provided for your class 1 is generated which calls the destructors of all member classes, otherwise the destructors of all member classes is called after your destructor code. In destructors you only need to delete memory allocated bynew
,malloc
or the likes. Either way, your code is calling the destructors tom_saTable
andm_saTables
and these destructors will free any memory associated with it. Having said that, yourCTableArray
is storing pointers, which means that the destructor for the table will only free the pointers, and not the actual data. You will need to enumerate each item and free its memory manually.CMyDoc::OnCloseDocument()
would be a good place to do this.INT_PTR nElements = m_saTables.GetCount();
for (int nIndex = 0; nIndex < nElements; ++nIndex) {
delete m_saTables.GetAt(nIndex); //assuming the elements inserted were created with "new CStringArray"
}At this code :
#if defined(DEBUG) || defined(_DEBUG)
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endifgive me the follow error :
error C2501: '_CrtSetDbgFlag' : missing storage-class or type specifiers
Because I use VC6 ?
-
At this code :
#if defined(DEBUG) || defined(_DEBUG)
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endifgive me the follow error :
error C2501: '_CrtSetDbgFlag' : missing storage-class or type specifiers
Because I use VC6 ?
Possibly. Try
#include <crtdbg.h>
and see if that fixes the problem, otherwise try_CrtDumpMemoryLeaks();
as the last statement in the App destructorCxxxApp::~CxxxApp()
I havn't used VC 6 in a many years, and it may not have these debugging functions. MSDN only has version 7.1 (2003) onwards. If I might make a suggestion, it might be an idea to upgrade. VC++ 7.1 (2003) is the latest version to support Windows 95, VC++ 8.0 (2005) is the latest version to support Windows 98/ME, VC++ 9.0 (2008) and 10.0 (2010) support Windows 2000 onwards. Unless you are wanting to support these older platforms I would suggest upgrading to at least VS 2008 Express. It is a free download from the Microsoft website with a Windows Live ID. -
Can you tell me if I use in corect way these classes , CTypedPtrArray & CStringArray ? These are member variable to CMyDoc class :
typedef CTypedPtrArray<CObArray,CStringArray*> CTableArray;
class CMyDoc : public CDocument
{
// Attributes
public:
CStringArray m_saTable;
CTableArray m_saTables;
...
}and here is code snipped for use of them :
m\_saTable.Add("String Test"); m\_saTables.Add(&m\_saTable); CStringArray\* saTest = m\_saTables.GetAt(0); CString sTest = saTest->GetAt(0); TRACE("\\n %s \\n",sTest);
but , where I need to delete elements ? I try to delete items in OnCloseDocument(...)
void CMyDoc::OnCloseDocument()
{
// TODO: Add your specialized code here and/or call the base classm\_saTable.RemoveAll(); m\_saTables.RemoveAll(); TRACE("\\n %d - %d \\n",m\_saTable.GetSize(),m\_saTables.GetSize()); CDocument::OnCloseDocument();
}
But with or without remove code , I didn't have memory leaks in debug window ... is really necesary to delete the items ? Any help , I will appreciated ! Thanks !
I don't know if is corect , but I think that I solve it :
// CMyDoc.h
typedef CTypedPtrArray CDumpArray;
class CMyDoc : public CDocument
{
protected: // create from serialization only
CMyDoc();
DECLARE_DYNCREATE(CMyDoc)// Attributes
public:
CDumpArray m_arrDump;
...
};// CMyDoc.cpp
CString sText = "one";
CStringArray* pTable = NULL;
pTable = new CStringArray();
pTable->Add(sText);
sText = "two";
pTable->Add(sText);m\_arrDump.Add(pTable); pTable = new CStringArray(); sText = "three"; pTable->Add(sText); sText = "four"; pTable->Add(sText); m\_arrDump.Add(pTable);
void CMyDoc::OnCloseDocument()
{
// TODO: Add your specialized code here and/or call the base classTRACE("\\n m\_arrDump %d \\n",m\_arrDump.GetSize()); CString sTemp; for(int n = 0;n < m\_arrDump.GetSize();++n) { TRACE("\\n StringArray no %d \\n",n); CStringArray\* pTable = m\_arrDump.GetAt(n); for(int t = 0;t < pTable->GetSize();++t) { sTemp = pTable->GetAt(t); TRACE("\\n %s \\n",sTemp); } } int nCount = m\_arrDump.GetSize(); for(int i = 0;i < nCount;++i)delete m\_arrDump.GetAt(i); m\_arrDump.RemoveAll(); TRACE("\\n m\_arrDump %d \\n",m\_arrDump.GetSize()); CDocument::OnCloseDocument();
}
-
I don't know if is corect , but I think that I solve it :
// CMyDoc.h
typedef CTypedPtrArray CDumpArray;
class CMyDoc : public CDocument
{
protected: // create from serialization only
CMyDoc();
DECLARE_DYNCREATE(CMyDoc)// Attributes
public:
CDumpArray m_arrDump;
...
};// CMyDoc.cpp
CString sText = "one";
CStringArray* pTable = NULL;
pTable = new CStringArray();
pTable->Add(sText);
sText = "two";
pTable->Add(sText);m\_arrDump.Add(pTable); pTable = new CStringArray(); sText = "three"; pTable->Add(sText); sText = "four"; pTable->Add(sText); m\_arrDump.Add(pTable);
void CMyDoc::OnCloseDocument()
{
// TODO: Add your specialized code here and/or call the base classTRACE("\\n m\_arrDump %d \\n",m\_arrDump.GetSize()); CString sTemp; for(int n = 0;n < m\_arrDump.GetSize();++n) { TRACE("\\n StringArray no %d \\n",n); CStringArray\* pTable = m\_arrDump.GetAt(n); for(int t = 0;t < pTable->GetSize();++t) { sTemp = pTable->GetAt(t); TRACE("\\n %s \\n",sTemp); } } int nCount = m\_arrDump.GetSize(); for(int i = 0;i < nCount;++i)delete m\_arrDump.GetAt(i); m\_arrDump.RemoveAll(); TRACE("\\n m\_arrDump %d \\n",m\_arrDump.GetSize()); CDocument::OnCloseDocument();
}
I cant see anything wrong with this, however a better solution for
CMyDoc::OnCloseDocument()
would bevoid CMyDoc::OnCloseDocument()
{
// TODO: Add your specialized code here and/or call the base classTRACE("\\n m\_arrDump %d \\n",m\_arrDump.GetSize()); CString sTemp; int nCount = m\_arrDump.GetSize(); for(int n = 0;n < nCount; ++n) { TRACE("\\n StringArray no %d \\n",n); CStringArray\* pTable = m\_arrDump.GetAt(n); for(int t = 0;t < pTable->GetSize();++t) { sTemp = pTable->GetAt(t); TRACE("\\n %s \\n",sTemp); } delete pTable; //You can delete these here for better code locality. You are only deleting the memory associated with them, not the item from the array. } //You dont need this next call unless you plan on reusing THIS instance of CMyDoc (which you shouldn't). CMyDoc::~CMyDoc() will clean it all up m\_arrDump.RemoveAll(); //Remove all the (now invalid) items from the array CDocument::OnCloseDocument();
}
-
I cant see anything wrong with this, however a better solution for
CMyDoc::OnCloseDocument()
would bevoid CMyDoc::OnCloseDocument()
{
// TODO: Add your specialized code here and/or call the base classTRACE("\\n m\_arrDump %d \\n",m\_arrDump.GetSize()); CString sTemp; int nCount = m\_arrDump.GetSize(); for(int n = 0;n < nCount; ++n) { TRACE("\\n StringArray no %d \\n",n); CStringArray\* pTable = m\_arrDump.GetAt(n); for(int t = 0;t < pTable->GetSize();++t) { sTemp = pTable->GetAt(t); TRACE("\\n %s \\n",sTemp); } delete pTable; //You can delete these here for better code locality. You are only deleting the memory associated with them, not the item from the array. } //You dont need this next call unless you plan on reusing THIS instance of CMyDoc (which you shouldn't). CMyDoc::~CMyDoc() will clean it all up m\_arrDump.RemoveAll(); //Remove all the (now invalid) items from the array CDocument::OnCloseDocument();
}
Thanks , works fine ! Thank you all !!!