отладка кода C++ с помощью шаблонов и STL с помощью gdb

что пользователи gdb здесь думают о своих возможностях в отношении отладки кода с помощью шаблонов и STL?

используете ли вы какие-либо трюки, чтобы упростить отладку? Возможно, некоторые скрипты Python? Или вы удовлетворены тем, как это происходит в настоящее время в gdb (ver 6.x, не пробовал 7.х еще)?

спасибо.

5 ответов


Я предполагаю, что вы имеете в виду визуализацию кода STL лучше (а не отладки режим которые дают безопасные итераторы и дополнительные проверки времени выполнения). Я не уверен, что вы смотрели на эти сообщения:

использование gdb

начиная с версии 7.0, GDB включает поддержку написания pretty-printers в Python. Симпатичные принтеры для STL классы распространяются с помощью GCC версии 4.5.0. Самая последняя версия этих принтеров всегда находится в репозитории libstdc++ svn. Чтобы включить эти принтеры, проверьте последние принтеры в локальном каталоге:

кроме того, попробуйте использовать KDevelop/DDD, если это возможно-они помогают.



мой любимый способ использования GDB-режим GDB в emacs. Вы получаете полную отладку визуального / исходного уровня, окно потока, окно стека (и т. д.)... Попробуйте, вы не будете разочарованы.

тем не менее, GDB обрабатывает отладку контейнеров STL просто отлично без специальных дополнений... Просто убедитесь, что вы строите с-g и без-ON (любого рода)...


Я не уверен, что вам разрешено добавлять код, или вы просто отлаживаете код, извините. Я написал простые функции утилиты с тех пор, я надеюсь, что вы найдете его полезным. Вы смогли напечатать содержание стандартных контейнеров легко. Нет кода конкретной платформы, пример использования (фактически тест-драйвер):

#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. Надеюсь, я сделаю это когда-нибудь:)

все, что вам нужно сделать, это включить этот файл["стример.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

ddd тоже отлично - мой любимый!