prashant_n_mhatre
asked on
dumping content of an object
is there any better way of dumping content of an object on screen/debugger watch window in vc++ debugger.
in case of STL objects, the debugger watch window is really painful.
I'm not willing to use autoexp.dat file.
in case of STL objects, the debugger watch window is really painful.
I'm not willing to use autoexp.dat file.
The problem is not with STL, but with the IDE.
VC++ IDE is clearly gear towards MFC, and makes little effort to interface properly with STL code.
VC++ IDE is clearly gear towards MFC, and makes little effort to interface properly with STL code.
i guess you are aware that watch window does intepretation as if it was runtime code.
so code casting and depth mem accessing can be made within the watch window..
such as a typical stl watch:
// depending on the template class
((CMyClass*) (*myiterator))->m_arrayinc lass[mycou nter];
or dumping complete class (without the stl jumbo)
(CMyClass*) *myiterator;
i agree STL "was" painful to debug.. but its all about getting used to and learn a good way to debug it.
so code casting and depth mem accessing can be made within the watch window..
such as a typical stl watch:
// depending on the template class
((CMyClass*) (*myiterator))->m_arrayinc
or dumping complete class (without the stl jumbo)
(CMyClass*) *myiterator;
i agree STL "was" painful to debug.. but its all about getting used to and learn a good way to debug it.
Here's some code for putting some STL types to your TRACE window.
#pragma warning (disable:4786)
#include <sstream>
#include <string>
#ifdef _DEBUG
namespace DEBUG_CODE
{
template<typename T>
void TraceSTL_Obj(const char* SourceFileName, int SourceLineNum, const char* ObjectName, T t, int Index = -1)
{
std::ostringstream oss;
oss << SourceFileName << "(" << SourceLineNum << ") : {" << ObjectName;
if (Index > -1) oss << "[" << Index << "]";
oss << "} = " << t << std::endl;
TRACE(oss.str().c_str());
}
template<typename T>
void TraceSTL_Container(const char* SourceFileName, int SourceLineNum, const char* ObjectName, T t)
{
int Idx = 0;
for (T::const_iterator i = t.begin();i != t.end();++i, ++Idx)
{
std::string szObjectName = ObjectName;
TraceSTL_Obj(SourceFileNam e, SourceLineNum, ObjectName, *i, Idx);
}
}
template<typename T>
void TraceSTL_AsscContainer(con st char* SourceFileName, int SourceLineNum, const char* ObjectName, T t)
{
int Idx = 0;
for (T::const_iterator i = t.begin();i != t.end();++i, ++Idx)
{
std::string szObjectName = ObjectName;
TraceSTL_Obj(SourceFileNam e, SourceLineNum, ObjectName, i->first, Idx);
}
}
}
#define TRACE_STL_OBJ(t) DEBUG_CODE::TraceSTL_Obj(_ _FILE__, __LINE__, #t, t)
#define TRACE_STL_CONTAINER(t) DEBUG_CODE::TraceSTL_Conta iner(__FIL E__, __LINE__, #t, t)
#define TRACE_STL_ASSC_CONTAINER(t ) DEBUG_CODE::TraceSTL_AsscC ontainer(_ _FILE__, __LINE__, #t, t)
#else //_DEBUG
#define TRACE_STL_OBJ(t)
#define TRACE_STL_CONTAINER(t)
#define TRACE_STL_ASSC_CONTAINER(t )
#endif //_DEBUG
#pragma warning (disable:4786)
#include <sstream>
#include <string>
#ifdef _DEBUG
namespace DEBUG_CODE
{
template<typename T>
void TraceSTL_Obj(const char* SourceFileName, int SourceLineNum, const char* ObjectName, T t, int Index = -1)
{
std::ostringstream oss;
oss << SourceFileName << "(" << SourceLineNum << ") : {" << ObjectName;
if (Index > -1) oss << "[" << Index << "]";
oss << "} = " << t << std::endl;
TRACE(oss.str().c_str());
}
template<typename T>
void TraceSTL_Container(const char* SourceFileName, int SourceLineNum, const char* ObjectName, T t)
{
int Idx = 0;
for (T::const_iterator i = t.begin();i != t.end();++i, ++Idx)
{
std::string szObjectName = ObjectName;
TraceSTL_Obj(SourceFileNam
}
}
template<typename T>
void TraceSTL_AsscContainer(con
{
int Idx = 0;
for (T::const_iterator i = t.begin();i != t.end();++i, ++Idx)
{
std::string szObjectName = ObjectName;
TraceSTL_Obj(SourceFileNam
}
}
}
#define TRACE_STL_OBJ(t) DEBUG_CODE::TraceSTL_Obj(_
#define TRACE_STL_CONTAINER(t) DEBUG_CODE::TraceSTL_Conta
#define TRACE_STL_ASSC_CONTAINER(t
#else //_DEBUG
#define TRACE_STL_OBJ(t)
#define TRACE_STL_CONTAINER(t)
#define TRACE_STL_ASSC_CONTAINER(t
#endif //_DEBUG
Example usage:
#pragma warning (disable:4786)
#include <sstream>
#include <string>
#include <list>
#include <vector>
#include <deque>
#include <map>
CTestTraceSTLApp::CTestTra ceSTLApp()
{
std::vector<std::string> MyStringVect;
MyStringVect.push_back("Te st1");
MyStringVect.push_back("Te st2");
MyStringVect.push_back("Te st3");
MyStringVect.push_back("Te st4");
TRACE_STL_CONTAINER(MyStri ngVect);
std::list<std::string> MyStringList;
MyStringList.push_back("Te stx1");
MyStringList.push_back("Te stx2");
MyStringList.push_back("Te stx3");
TRACE_STL_CONTAINER(MyStri ngList);
std::map<int, std::string> MyStringMap;
MyStringMap[69] = "Test69";
MyStringMap[77] = "Test77";
MyStringMap[33] = "Test33";
TRACE_STL_ASSC_CONTAINER(M yStringMap );
std::string test1 = "Hello World! from std::string";
TRACE_STL_OBJ(test1);
CString test2 = "Hello World! from CString";
TRACE_STL_OBJ(test2);
AfxMessageBox("Check your debug window for above data");
}
#pragma warning (disable:4786)
#include <sstream>
#include <string>
#include <list>
#include <vector>
#include <deque>
#include <map>
CTestTraceSTLApp::CTestTra
{
std::vector<std::string> MyStringVect;
MyStringVect.push_back("Te
MyStringVect.push_back("Te
MyStringVect.push_back("Te
MyStringVect.push_back("Te
TRACE_STL_CONTAINER(MyStri
std::list<std::string> MyStringList;
MyStringList.push_back("Te
MyStringList.push_back("Te
MyStringList.push_back("Te
TRACE_STL_CONTAINER(MyStri
std::map<int, std::string> MyStringMap;
MyStringMap[69] = "Test69";
MyStringMap[77] = "Test77";
MyStringMap[33] = "Test33";
TRACE_STL_ASSC_CONTAINER(M
std::string test1 = "Hello World! from std::string";
TRACE_STL_OBJ(test1);
CString test2 = "Hello World! from CString";
TRACE_STL_OBJ(test2);
AfxMessageBox("Check your debug window for above data");
}
You can write a custom DLL for this purpose.
How-To and sample code:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vcsample/html/vcsameeaddinsampledebuggingexpressionevaluatoradd-in.asp
How-To and sample code:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vcsample/html/vcsameeaddinsampledebuggingexpressionevaluatoradd-in.asp
Ooops sorry i didn't see the last line in your question :)
ASKER
Thank you all.
I tried out a small test program
//------------------------ ----------
#pragma warning (disable:4786)
#include <string>
#include <list>
#include <iostream>
using namespace std;
typedef list<string> STRINGLIST;
void main()
{
STRINGLIST m_IssueList;
m_IssueList.insert(m_Issue List.end() , "AAA");
m_IssueList.insert(m_Issue List.end() , "BBB");
m_IssueList.insert(m_Issue List.end() , "CCC");
STRINGLIST::iterator Issues;
for(Issues = m_IssueList.begin(); Issues != m_IssueList.end(); Issues++)
{
cerr << *Issues << endl;
}
}
//------------------------ ---------- ---
What is the simplest way to see the content of (*Issues) and m_IssueList in debugger watch window?
I tried out a small test program
//------------------------
#pragma warning (disable:4786)
#include <string>
#include <list>
#include <iostream>
using namespace std;
typedef list<string> STRINGLIST;
void main()
{
STRINGLIST m_IssueList;
m_IssueList.insert(m_Issue
m_IssueList.insert(m_Issue
m_IssueList.insert(m_Issue
STRINGLIST::iterator Issues;
for(Issues = m_IssueList.begin(); Issues != m_IssueList.end(); Issues++)
{
cerr << *Issues << endl;
}
}
//------------------------
What is the simplest way to see the content of (*Issues) and m_IssueList in debugger watch window?
Use the STL trace code I posted above.
TRACE_STL_ASSC_CONTAINER(m _IssueList );
TRACE_STL_OBJ(*Issues);
TRACE_STL_ASSC_CONTAINER(m
TRACE_STL_OBJ(*Issues);
Correction:
TRACE_STL_CONTAINER(m_Issu eList);
TRACE_STL_OBJ(*Issues);
TRACE_STL_CONTAINER(m_Issu
TRACE_STL_OBJ(*Issues);
Or you can modify your code to the following:
for(Issues = m_IssueList.begin(); Issues != m_IssueList.end(); Issues++)
{
//cerr << *Issues << endl;
TRACE("%s",Issues->c_str() );
}
for(Issues = m_IssueList.begin(); Issues != m_IssueList.end(); Issues++)
{
//cerr << *Issues << endl;
TRACE("%s",Issues->c_str()
}
ASKER
TRACE doesn't work in console application. Do I need to write my own TRACE macro?
I guess simple 'printf' will work.
I guess simple 'printf' will work.
TRACE does work from a console application:
You need to include "afx.h"
Example:
#include "stdafx.h"
#include <stdlib.h>
#include <afx.h>
int main(int argc, char* argv[])
{
TRACE("Hello from TRACE");
system("pause");
return 0;
}
You need to include "afx.h"
Example:
#include "stdafx.h"
#include <stdlib.h>
#include <afx.h>
int main(int argc, char* argv[])
{
TRACE("Hello from TRACE");
system("pause");
return 0;
}
You might need to modify your project settings under C++ TAB and [Code Generation], and change run-time library to Multithread.
Only do this if you get errors like the following:
nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __endthreadex
nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __beginthreadex
Only do this if you get errors like the following:
nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __endthreadex
nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __beginthreadex
ASKER
Do I need to create win32 application? I tried including <afx.h> in console application. It gives linking error like:
Linking...
nafxcwd.lib(afxmem.obj) : error LNK2005: "void __cdecl operator delete(void *)" (??3@YAXPAX@Z) already defined in libcpd.lib(delop.obj)
nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __endthreadex
nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __beginthreadex
Debug/kkSTL.exe : fatal error LNK1120: 2 unresolved externals
Error executing link.exe.
Linking...
nafxcwd.lib(afxmem.obj) : error LNK2005: "void __cdecl operator delete(void *)" (??3@YAXPAX@Z) already defined in libcpd.lib(delop.obj)
nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __endthreadex
nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __beginthreadex
Debug/kkSTL.exe : fatal error LNK1120: 2 unresolved externals
Error executing link.exe.
As I stated in previous comment, you need to modify your project settings under C++ TAB and [Code Generation], and change run-time
library to Multithread.
library to Multithread.
ASKER
Oops...Your comment was not there when I'd started typing my last comment. I did the same you suggested..still getting the following error..
Linking...
nafxcwd.lib(afxmem.obj) : error LNK2005: "void __cdecl operator delete(void *)" (??3@YAXPAX@Z) already defined in libcpmtd.lib(delop.obj)
LINK : warning LNK4098: defaultlib "LIBCMT" conflicts with use of other libs; use /NODEFAULTLIB:library
Debug/kkSTL.exe : fatal error LNK1169: one or more multiply defined symbols found
Error executing link.exe.
tried using /NODEFAULTLIB -- doesn't work
Linking...
nafxcwd.lib(afxmem.obj) : error LNK2005: "void __cdecl operator delete(void *)" (??3@YAXPAX@Z) already defined in libcpmtd.lib(delop.obj)
LINK : warning LNK4098: defaultlib "LIBCMT" conflicts with use of other libs; use /NODEFAULTLIB:library
Debug/kkSTL.exe : fatal error LNK1169: one or more multiply defined symbols found
Error executing link.exe.
tried using /NODEFAULTLIB -- doesn't work
OK, lets change TRACE to what it should be.
Use OutputDebugString instead for CONSOLE.
And replace "afx.h" with the following includes:
#include <windows.h>
#include <Winbase.h>
Also you can change you project setting back to single thread.
Use OutputDebugString instead for CONSOLE.
And replace "afx.h" with the following includes:
#include <windows.h>
#include <Winbase.h>
Also you can change you project setting back to single thread.
ASKER
No link error...but no output getting displayed on screen.
#include <windows.h>
#include <Winbase.h>
If you use OutputDebugString, you can't just use it like TRACE, because OutputDebugString, takes a single string, and not a variable argument type.
You can use the code I posted, and just change TRACE to OutputDebugString.
#include <Winbase.h>
If you use OutputDebugString, you can't just use it like TRACE, because OutputDebugString, takes a single string, and not a variable argument type.
You can use the code I posted, and just change TRACE to OutputDebugString.
Try createing a new test console application, and paste the following code into the main.cpp file:
#include "stdafx.h"
#include <windows.h>
#include <Winbase.h>
#pragma warning (disable:4786)
#include <sstream>
#include <string>
#include <list>
#include <vector>
#include <deque>
#include <map>
#ifdef _DEBUG
namespace DEBUG_CODE
{
template<typename T>
void TraceSTL_Obj(const char* SourceFileName, int SourceLineNum, const char* ObjectName, T t, int Index = -1)
{
std::ostringstream oss;
oss << SourceFileName << "(" << SourceLineNum << ") : {" << ObjectName;
if (Index > -1) oss << "[" << Index << "]";
oss << "} = " << t << std::endl;
OutputDebugString(oss.str( ).c_str()) ;
}
template<typename T>
void TraceSTL_Container(const char* SourceFileName, int SourceLineNum, const char* ObjectName, T t)
{
int Idx = 0;
for (T::const_iterator i = t.begin();i != t.end();++i, ++Idx)
{
std::string szObjectName = ObjectName;
TraceSTL_Obj(SourceFileNam e, SourceLineNum, ObjectName, *i, Idx);
}
}
template<typename T>
void TraceSTL_AsscContainer(con st char* SourceFileName, int SourceLineNum, const char* ObjectName, T t)
{
int Idx = 0;
for (T::const_iterator i = t.begin();i != t.end();++i, ++Idx)
{
std::string szObjectName = ObjectName;
TraceSTL_Obj(SourceFileNam e, SourceLineNum, ObjectName, i->first, Idx);
}
}
}
#define TRACE_STL_OBJ(t) DEBUG_CODE::TraceSTL_Obj(_ _FILE__, __LINE__, #t, t)
#define TRACE_STL_CONTAINER(t) DEBUG_CODE::TraceSTL_Conta iner(__FIL E__, __LINE__, #t, t)
#define TRACE_STL_ASSC_CONTAINER(t ) DEBUG_CODE::TraceSTL_AsscC ontainer(_ _FILE__, __LINE__, #t, t)
#else //_DEBUG
#define TRACE_STL_OBJ(t)
#define TRACE_STL_CONTAINER(t)
#define TRACE_STL_ASSC_CONTAINER(t )
#endif //_DEBUG
int main(int argc, char* argv[])
{
std::vector<std::string> MyStringVect;
MyStringVect.push_back("Te st1");
MyStringVect.push_back("Te st2");
MyStringVect.push_back("Te st3");
MyStringVect.push_back("Te st4");
TRACE_STL_CONTAINER(MyStri ngVect);
std::list<std::string> MyStringList;
MyStringList.push_back("Te stx1");
MyStringList.push_back("Te stx2");
MyStringList.push_back("Te stx3");
TRACE_STL_CONTAINER(MyStri ngList);
std::map<int, std::string> MyStringMap;
MyStringMap[69] = "Test69";
MyStringMap[77] = "Test77";
MyStringMap[33] = "Test33";
TRACE_STL_ASSC_CONTAINER(M yStringMap );
std::string test1 = "Hello World! from std::string";
TRACE_STL_OBJ(test1);
system("pause");
return 0;
}
#include "stdafx.h"
#include <windows.h>
#include <Winbase.h>
#pragma warning (disable:4786)
#include <sstream>
#include <string>
#include <list>
#include <vector>
#include <deque>
#include <map>
#ifdef _DEBUG
namespace DEBUG_CODE
{
template<typename T>
void TraceSTL_Obj(const char* SourceFileName, int SourceLineNum, const char* ObjectName, T t, int Index = -1)
{
std::ostringstream oss;
oss << SourceFileName << "(" << SourceLineNum << ") : {" << ObjectName;
if (Index > -1) oss << "[" << Index << "]";
oss << "} = " << t << std::endl;
OutputDebugString(oss.str(
}
template<typename T>
void TraceSTL_Container(const char* SourceFileName, int SourceLineNum, const char* ObjectName, T t)
{
int Idx = 0;
for (T::const_iterator i = t.begin();i != t.end();++i, ++Idx)
{
std::string szObjectName = ObjectName;
TraceSTL_Obj(SourceFileNam
}
}
template<typename T>
void TraceSTL_AsscContainer(con
{
int Idx = 0;
for (T::const_iterator i = t.begin();i != t.end();++i, ++Idx)
{
std::string szObjectName = ObjectName;
TraceSTL_Obj(SourceFileNam
}
}
}
#define TRACE_STL_OBJ(t) DEBUG_CODE::TraceSTL_Obj(_
#define TRACE_STL_CONTAINER(t) DEBUG_CODE::TraceSTL_Conta
#define TRACE_STL_ASSC_CONTAINER(t
#else //_DEBUG
#define TRACE_STL_OBJ(t)
#define TRACE_STL_CONTAINER(t)
#define TRACE_STL_ASSC_CONTAINER(t
#endif //_DEBUG
int main(int argc, char* argv[])
{
std::vector<std::string> MyStringVect;
MyStringVect.push_back("Te
MyStringVect.push_back("Te
MyStringVect.push_back("Te
MyStringVect.push_back("Te
TRACE_STL_CONTAINER(MyStri
std::list<std::string> MyStringList;
MyStringList.push_back("Te
MyStringList.push_back("Te
MyStringList.push_back("Te
TRACE_STL_CONTAINER(MyStri
std::map<int, std::string> MyStringMap;
MyStringMap[69] = "Test69";
MyStringMap[77] = "Test77";
MyStringMap[33] = "Test33";
TRACE_STL_ASSC_CONTAINER(M
std::string test1 = "Hello World! from std::string";
TRACE_STL_OBJ(test1);
system("pause");
return 0;
}
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Or you can modify your code to the following:
for(Issues = m_IssueList.begin(); Issues != m_IssueList.end(); ++Issues)//You should practice using prefix
{
//cerr << *Issues << endl;
OutputDebugString(Issues-> c_str());
}
for(Issues = m_IssueList.begin(); Issues != m_IssueList.end(); ++Issues)//You should practice using prefix
{
//cerr << *Issues << endl;
OutputDebugString(Issues->
}
The simplest way to see it in the Watch window would look like this:
char* pTmp;
for(Issues = m_IssueList.begin(); Issues != m_IssueList.end(); Issues++)
{
pTmp= Issues->c_str();
}
Then put a watch on pTmp. Or just rest the mouse over it and an infotip will pop up! You could even use:
#if _DEBUG
pTmp= Issues->c_str();
#endif
so that it won't interfere with the release build.
-- Dan
char* pTmp;
for(Issues = m_IssueList.begin(); Issues != m_IssueList.end(); Issues++)
{
pTmp= Issues->c_str();
}
Then put a watch on pTmp. Or just rest the mouse over it and an infotip will pop up! You could even use:
#if _DEBUG
pTmp= Issues->c_str();
#endif
so that it won't interfere with the release build.
-- Dan
ASKER
Thank you all !!!
I agree, and this is one of the prime reasons that I refuse to use STL. The other is that tracing through the source code is excruciating. Simple program errors that should take a few minutes to isolate and debug turn into all-night marathons.
Contrast the std::string class to MFC's CString. Both have similar features. But with the latter, the code is clear and the data is at your fingertips.
About the only thing you can do is write a custom object-dumper. It's output can go to the Debug window (TRACE) or to a log file. The alternaive is avoid STL.
-- Dan