Author Topic: Debugging C++ code and STL classes  (Read 16738 times)

ghorwin

  • Guest
Debugging C++ code and STL classes
« on: September 29, 2006, 11:25:32 pm »
Hi there,

I believe that this is a problem a few people have run into and maybe there has been some discussion about this already. If yes, please point me to the appropriate thread...

In my (and my students) programs STL classes are extensively used, mostly std::string, std::vector, std::list and std::map. Debugging source code with CodeBlocks works so far only satisfactorily for std::string, and that only for simply showing the content. From the perspective of a user (e.g. imagine a student learning C++), it would be nice to have some more features, as outlined below.

As G++ doesn't compile inlined template functions unless they are used, I created a header file for my students, that includes a class like this:

Code: cpp
class _STLDebugHelper {
  public:
    _STLDebugHelper() {
      std::vector<double> d;
      d.size(); d.front(); d.back();
      d.push_back(10); d[0] = 2; d.at(0) = 2;
      d.begin(); d.end();
      std::vector<double>::iterator it;
      ++it; it++; --it; it--;*it;
      // ... same for other STL classes

    }
} __STLDebugHelper;

By including the header (in only one of the implementation files) at least the typical STL container functions are available through the debugger.

However, when it comes to displaying and evaluating variables using the debugger and the UI, there are still some features that would be quite helpful:

- local watches of STL container types should be collapsed when first shown in the debugger (try debugging a program with 10 locally declared STL classes or a class with 20 stl type member variables... you need a few minutes just to get an overview of what you are actually looking at)
- locally watched std::string types should show the content like it is done when manually adding a watch for a variable of type std::string
- watching ranges of elements in std::vector in the style of vector[15] - 10 elements = [0, 1, 2, 3, 4, 5, 6, 7, 2,3] should be possible

I believe that these features are rather UI features than something to be directly implemented into GDB. Now, does somebody actively work on enhancing debugging features/display in CodeBlocks? If nobody has the time to look into that, I could maybe help enhancing the debugging capabilities of CodeBlocks, but I would appreciate some help for where to get started (basically some info on which class does the GDB parsing, and how and where the debugging treeview is updated). Also watched variables may need additional properties, such as the number of elements to display (in the case of the std::vector).

Thanks a lot in advance for any improvements regarding the debugger, since I believe it is a very important tool for students and active programmers alike.

Andreas Nicolai

Offline mandrav

  • Project Leader
  • Administrator
  • Lives here!
  • *****
  • Posts: 4315
    • Code::Blocks IDE
Re: Debugging C++ code and STL classes
« Reply #1 on: September 30, 2006, 12:00:33 am »
Quote
- local watches of STL container types should be collapsed when first shown in the debugger

Yesterday's nightly (which was actually released a little while ago), has improved the watches tree. This (not-expanded watches) is the default now.

Quote
- locally watched std::string types should show the content like it is done when manually adding a watch for a variable of type std::string

That's on my todo list.

Quote
- watching ranges of elements in std::vector in the style of vector[15] - 10 elements = [0, 1, 2, 3, 4, 5, 6, 7, 2,3] should be possible

The infrastructure is there, I just haven't implemented this yet.
Be patient!
This bug will be fixed soon...

ghorwin

  • Guest
Re: Debugging C++ code and STL classes
« Reply #2 on: September 30, 2006, 10:02:27 pm »
Excellent! Just downloaded the last build and this is a useful default (maybe expanding just the root "local watches" and "function arguments" tree nodes would be a tiny little bit better :-)
Anyway, I'm looking forward to the other extensions. Thanks already in advance!

Andreas

Offline Game_Ender

  • Lives here!
  • ****
  • Posts: 551
Re: Debugging C++ code and STL classes
« Reply #3 on: September 30, 2006, 10:28:46 pm »
It is important to note that the std::string support is done through a debugger script that is registered for the std::string type.  You can create you own custom scripts to make the viewing of other std classes easier as well.  You can also create debugger scripts for you own custom types, possible utilizing a universal toString(), like Java does, to make them easier to write.

ghorwin

  • Guest
Re: Debugging C++ code and STL classes
« Reply #4 on: October 02, 2006, 10:06:13 pm »
After looking at the gdb_types.script and the Debugger Wikipage I'm pretty sure that I can design some useful scripts for evaluating the remaining std containers...

However, while trying out some stuff here, I ran into a problem which could be solved by adding a new feature.
When debugging std containers (or other classes with dynamically allocated memory), it is generally necessary to check a certain condition (e.g. is the pointer to the dynamically allocated memory actually valid and can be dereferenced?) before evaluating the content of that datatype. In the case of the std::string one can observe this necessity by adding a watch to an empty string - the debugger throws an exception.

While this can never fully prevented (see example below), I would propose two additions to the CodeBlocks watch evaluation code:

1. easy fix: somehow wrap the debugger exception and instead of displaying the exception text in the watch window simply write out
my_variable = <cannot be evaluated>

2. more difficult to do: allow a debugger script somehow to evaluate conditions and compose the debugger command based on the evaluation of this condition.

Example 1 - a case were you cannot safely prevent debugger exception:
---
Imagine a user evaluating a std::vector  using v[10], the vector has only 5 elements, but a capacity of 15. So debugging v[10] is valid, even though index >= 5. Now of course, one could parse check the capacity of the vector first, but if that is not possible, the debugger will always throw an exception.


Example 2 - a debugger script (pseudo-code) that safely evaluates a std::vector using generic functions and the specific g++ implementation:
---
Using generic functions, one would need std::vector::capacity() and std::vector::begin(), possibly std::vector::size() if the debugger output should indicate that one examines values past the 'official' size of the vector. The problem with generic function is that they may not be available, if they are not used somewhere in the program and thus compiled.

1. compose debugger command to evaluate capacity() and return an integer number
2. compare start + count < capacity, and only evaluate further if true
3. compose debugger command to extract data from start... start+count

Using g++ implementation, things become easier and more reliable:

1. compose debugger command to evaluate end_ptr = myvec._M_impl._M_end_of_storage
2. compose debugger command to evaluate start_ptr = myvec._M_impl._M_start
3. check if start + count < end_ptr - start_ptr and start_ptr != 0, only continue parsing if true
4. compose debugger command to extract data from start... start+count

Now, how much effort would it make to allow the definition of conditional variables for a debugger type which could then be used in the actual parse function? Or would this already be possible with the existing design?

Bye,
Andreas

ghorwin

  • Guest
Re: Debugging C++ code and STL classes
« Reply #5 on: October 02, 2006, 11:30:54 pm »
After some testing I could compose a "safe" GDB command to evaluate a std::vector:

Code: cpp
p   (vec._M_impl._M_start == vec._M_impl._M_end_of_storage) ? "<empty>" : ((start+count) < (vec._M_impl._M_end_of_storage - vec._M_impl._M_start)) ? vec._M_impl._M_start@count : "<index out of range>"

This, however, returns either one of the error strings or the content of the vector range in hex, so one of the following:

"<empty>"
"<index out of range>"
{0x3e4f58, 0x3e5f00, 0x3e5f58, 0x3e5f70, 0x3e6f18, 0x3e6f18, 0x3eae20, 0x3ebdc8, 0x3ebdc8, 0x3e6f30}

regardless of the actual type of the vector (the example above was obtained from a vector<double>).

Using
p /f ...

I will get the content of the vector<double> correctly, but the strings are converted to numbers :-( So, the parsing and conversion of each type would have to be done either in Parse_StlVector or in the CodeBlocks GUI.

Any suggestion about how to do this best?

Btw, the option of floating point format for the watched expression is missing: "Decimal" is misleading (should be "Signed" or "Integer") and "Floating point" should be added.

Bye,
Andreas


Offline adfm

  • Multiple posting newcomer
  • *
  • Posts: 21
Re: Debugging C++ code and STL classes
« Reply #6 on: May 19, 2009, 12:48:53 pm »
hey,

sorry for waking this thread up, but I am wondering what is the status of the proposed solutions for debugging stl!

What I get when I try to watch a string and a vector of this sort

Code
    vector<int> bla;
    bla.push_back(1);
    bla.push_back(2);
    bla.push_back(3);
    bla.push_back(4);
    bla.push_back(5);

    string blob="Hello World";

is something like...

[img=http://img231.imageshack.us/img231/5286/debugoutput.png]

what's all this stuff about anyway? shouldn't be something pretty much simpler than this?


Regards
Andre
« Last Edit: May 19, 2009, 01:11:15 pm by adfm »