【问题标题】:debugging C++ code with templates and STL with gdb使用模板调试 C++ 代码,使用 gdb 调试 STL
【发布时间】:2009-10-23 01:08:30
【问题描述】:

这里的 gdb 用户如何看待它在使用模板和 STL 调试代码方面的功能?

您是否使用任何技巧来简化调试?也许是一些 Python 脚本?或者你对gdb目前的方式满意吗(6.x版,7.x还没试过)?

谢谢。

【问题讨论】:

  • 感谢 Amro,非常感谢。我期待几天后在我的 Debian 机器(运行测试)中获得 GDB 7.0。同时,我正在尝试了解如何以正确的方式在 .gdbinit 中进行设置。问候。

标签: c++ debugging templates stl gdb


【解决方案1】:

这可能会有所帮助: GDB STL Support Tools

【讨论】:

    【解决方案2】:

    我假设您的意思是更好地可视化 STL 代码(而不是提供安全迭代器和额外运行时检查的 debug mode)。我不确定你是否看过这些帖子:

    使用 gdb

    从 7.0 版开始,GDB 支持在 Python 中编写漂亮的打印机。用于 STL 类的漂亮打印机随 GCC 4.5.0 版本一起分发。这些打印机的最新版本始终可以在 libstdc++ svn 存储库中找到。要启用这些打印机,请将最新的打印机签出到本地目录:

    另外,如果可能的话,尝试使用 KDevelop/DDD -- 他们确实有帮助。

    【讨论】:

      【解决方案3】:

      我最喜欢使用 GDB 的方式是 emacs 中的 GDB 模式。您可以获得完整的可视化/源代码级调试、线程窗口、堆栈窗口(等等)...试试吧,您不会失望的。

      也就是说,GDB 可以很好地处理 STL 容器的调试,没有特殊的附加组件...只要确保您正在构建 WITH -g,并且没有 -ON(任何类型的)...

      【讨论】:

        【解决方案4】:

        我不确定您是否可以添加代码,或者您只是在调试代码,抱歉。一段时间以来,我写了一个简单的实用函数,希望你觉得它有用。您可以轻松打印标准容器的内容。没有特定于平台的代码,使用示例(实际上是测试驱动程序):

        #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);
        }
        

        我还没有为 Boost 容器编写代码。希望有一天我会这样做:)

        你所要做的就是包含这个文件[“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
        

        【讨论】:

        • 感谢代码示例和示例。目前我试图不为此使用任何外部代码。理想情况下,我希望 gdb 要么在本地进行(已经提到了漂亮的打印),要么为 gdb 制作一个脚本来帮助它这样做。从其他回复来看,我希望新版本的 gdb 在这方面做得更好。而且,顺便说一句,我正在编写自己的代码。问候。
        【解决方案5】:

        ddd 也很棒——我的最爱!

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-01-07
          • 1970-01-01
          • 2013-09-29
          • 2015-01-11
          • 2010-09-30
          • 2018-11-20
          • 1970-01-01
          相关资源
          最近更新 更多