debugging C++ code with templates and STL with gdb

后端 未结 5 707
渐次进展
渐次进展 2020-12-28 10:29

What do gdb users here think about its capabilities in regards to debugging code with templates and STL?

Do you use any tricks to make the debugging any simpler? Per

相关标签:
5条回答
  • 2020-12-28 11:01

    I am assuming that you mean visualizing STL code better (and not the debug mode which give safe iterators and additional runtime checks). I am not sure if you have looked at these posts:

    • GNU GCC Documentation: Debugging Support

    Using gdb

    Starting with version 7.0, GDB includes support for writing pretty-printers in Python. Pretty printers for STL classes are distributed with GCC from version 4.5.0. The most recent version of these printers are always found in libstdc++ svn repository. To enable these printers, check-out the latest printers to a local directory:

    • Pretty printing STL lists

    Also, try using KDevelop/DDD if possible -- they do help.

    0 讨论(0)
  • 2020-12-28 11:01

    ffffd is great too -- my favorite!

    0 讨论(0)
  • 2020-12-28 11:02

    This may be of help: GDB STL Support Tools

    0 讨论(0)
  • 2020-12-28 11:04

    I am not sure if you are allowed to add code, or you are just debugging the code, Sorry. I wrote a simple utility functions since a while, I hope you find it useful. You could print the contents of standard containers easily. There is no platform specific code, an example of usage(the test-driver actually):

    #include <iostream>
    #include <fstream>
    #include <iomanip>
    #include <string>
    
    #include <vector>
    #include <list>
    #include <stack>
    #include <queue>
    #include <deque>
    #include <set>
    #include <map>
    
    #include <boost/array.hpp>
    #include <boost/assign.hpp>
    #include "streamer.hpp"
    
    
    const std::size_t consoleWidth = 80;
    
    std::ostream& newline_if_not_console(std::ostream& outputstream)
    {
        if(&outputstream != & std::cout)
        {
            outputstream << std::endl;
        }
    
        return outputstream;
    }
    
    void STL_test_ostream(std::ostream& out)
    {
        using namespace boost::assign;
        using namespace streamer;
    
        double iDoubleArray[] = {0.1, 1.2, 2.3, 3.4, 4.5}; // It could be of any type!
        std::vector<int>                iVec;
        std::list<int>                  iList;
        std::deque<int>                 iDeque;
        std::stack<int>                 iStack;
        std::queue<int>                 iQueue;
        std::priority_queue<int>        iPriorityQueue;
        std::set<int>                   iSet;
        std::map<int, std::string>      iMap;
    
        iVec            +=  0, 1, 2, 3, 4, 5;
        iList           +=  0, 1, 2, 3, 4, 5;
        iDeque          +=  0, 1, 2, 3, 4, 5;
        iStack          +=  0, 1, 2, 3, 4, 5;
        iQueue          +=  0, 1, 2, 3, 4, 5;
        iPriorityQueue  +=  0, 1, 2, 3, 4, 5;
        iSet            +=  0, 1, 2, 3, 4, 5;
        insert(iMap)
            (   1 , "one"   )
            (   2 , "two"   )
            (   3 , "three" )
            (   4 , "four"  )
            (   5 , "five"  );
    
        out << std::string(consoleWidth, '=') << newline_if_not_console
            << "STL Test..." << std::endl
            << std::string(consoleWidth, '=') << newline_if_not_console;
    
        out << "Native Array   = "  <<  iDoubleArray    << std::endl;
        out << "vector         = "  <<  iVec            << std::endl;
        out << "list           = "  <<  iList           << std::endl;
        out << "deque          = "  <<  iDeque          << std::endl;
        out << "queue          = "  <<  iQueue          << std::endl;
        out << "stack          = "  <<  iStack          << std::endl;
        out << "priority_queue = "  <<  iPriorityQueue  << std::endl;
        out << "set            = "  <<  iSet            << std::endl;
        out << "map            = "  <<  iMap            << std::endl;
    
        out << std::string(consoleWidth, '=') << std::endl;
    }
    
    void Boost_test_ostream(std::ostream& out)
    {
        out << std::string(consoleWidth, '=') << newline_if_not_console
        << "Boost Test..."  << std::endl
        << std::string(consoleWidth, '=') << newline_if_not_console;
    
    }
    
    int main()
    {
        std::ofstream stl("STL_test_ostream.txt"),
                    boost("Boost_test_ostream.txt");
    
        STL_test_ostream(std::cout);
        Boost_test_ostream(std::cout);
    
        STL_test_ostream(stl);
        Boost_test_ostream(boost);
    }
    

    I haven't wrote the code for Boost containers yet. Hopefully, I'll do it sometime :)

    All what you have to do, is to include this file["streamer.hpp"]:

    #ifndef DATASTRUCTRE_STREAMER
    #define DATASTRUCTRE_STREAMER
    
    #include <stack>
    #include <queue>
    #include <boost/array.hpp>
    #include <functional>
    #include <memory>
    
    namespace streamer
    {
    
        // one-value data structure streaming function
        template <class Container, class Stream>
        Stream& printOneValueContainer(Stream& outputstream, const Container& container)
        {
            Container::const_iterator beg = container.begin();
    
            outputstream << "[";
    
            while(beg != container.end())
            {
                outputstream << " " << *beg++;
            }
    
            outputstream << " ]";
    
            return outputstream;
        }
    
        // pair-value data structure streaming function
        template <class Container, class Stream>
        Stream& printPairValueContainer(Stream& outputstream, const Container& container)
        {
            Container::const_iterator beg = container.begin();
    
            outputstream << "[";
    
            while(beg != container.end())
            {
                outputstream << " " << "<" << beg->first << " , " << beg->second << ">";
                beg++;
            }
    
            outputstream << " ]";
    
            return outputstream;
        }
    
    
    
        /*
        *************************************************************
        C++ Standard Library
        *************************************************************
        */
    
        // Sequence Containers.
    
        // vector, list, deque
        template
        < class Type
        , template<class Type, class Allocator = std::allocator<Type> > class Container
        , class Stream
        >
        Stream& operator<<(Stream& outputstream, const Container<Type>& container)
        {
            return printOneValueContainer(outputstream, container);
        }
    
        // Associative Containers.
    
        // set, multiset
        template
            < class Key
            , template<class KeyType, class Traits = std::less<KeyType>, class Allocator = std::allocator<KeyType> > class Container
            , class Stream
            >
        Stream& operator<<(Stream& outputstream, const Container<Key>& container)
        {
            return printOneValueContainer(outputstream, container);
        }
    
        // map, multimap
        template
            < class Key, class Value
            , template<class KeyType, class ValueType, class Traits = std::less<KeyType>, class Allocator = std::allocator<std::pair<const KeyType, ValueType> > > class Container
            , class Stream
            >
        Stream& operator<<(Stream& outputstream, const Container<Key, Value>& container)
        {
            return printPairValueContainer(outputstream, container);
        }
    
        // Adapters.
    
        // stack, queue
        template < class Type, class Container >
        const Container& container(const std::stack<Type, Container>& stack)
        {
            struct HackedStack : private std::stack<Type, Container>
            {
                static const Container& container(const std::stack<Type, Container>& stack)
                {
                    return stack.*&HackedStack::c;
                }
            };
    
            return HackedStack::container(stack);
        }
    
        template < class Type, class Container >
        const Container& container(const std::queue<Type, Container>& queue)
        {
            struct HackedQueue : private std::queue<Type, Container>
            {
                static const Container& container(const std::queue<Type, Container>& queue)
                {
                    return queue.*&HackedQueue::c;
                }
            };
    
            return HackedQueue::container(queue);
        }
    
        template
            < class Type
            , template <class Type, class Container = std::deque<Type> > class Adapter
            , class Stream
            >
        Stream& operator<<(Stream& outputstream, const Adapter<Type>& adapter)
        {
            return printOneValueContainer(outputstream, container(adapter));
        }
    
        // priority_queue
        template < class Type, class Container, class Compare >
        const Container& container(const std::priority_queue<Type, Container, Compare>& priorityQue)
        {
            struct HackedProiorityQueue : private std::priority_queue<Type, Container, Compare>
            {
                static const Container& container(const std::priority_queue<Type, Container, Compare>& priorityQue)
                {
                    return priorityQue.*&HackedProiorityQueue::c;
                }
            };
    
            return HackedProiorityQueue::container(priorityQue);
        }
    
        template < class Type, class Container, class Compare, class Stream >
        Stream& operator<<(Stream& outputstream, const std::priority_queue<Type, Container, Compare>& adapter)
        {
            return printOneValueContainer(outputstream, container(adapter));
        }
    
        /*
        *************************************************************
        C++ Native Arrays
        *************************************************************
        */
    
        template <class Type, std::size_t size, class Stream>
        Stream& operator<<(Stream& outputstream, Type (&array)[size])
        {
            outputstream << "[";
    
            for(std::size_t i = 0; i < size; ++i)
            {
                outputstream << " " << array[i];
            }
    
            outputstream << " ]";
    
            return outputstream;
        }
    
        /*
        *************************************************************
            Boost
        *************************************************************
        */
    }
    
    #endif
    
    0 讨论(0)
  • 2020-12-28 11:07

    My favorite way to use GDB is GDB mode in emacs. You get full visual/source level debugging, thread window, stack window (etc)... Try it out, you won't be disappointed.

    That said, GDB handles debugging of STL containers just fine with no special add ons... Just make sure you're building WITH -g, and without -ON (of any kind)...

    0 讨论(0)
提交回复
热议问题