jeudi 25 février 2016

std::tuple args life cycle?

I am implementing a logger which saves print args into a tuple. the tuple is used in the logger thread.

template<typename... Ts>
class LogTransaction
{
public:

    template<typename... Args>
    LogTransaction(Args&&... _args) : args(std::forward<Args>(args)...)
    {}

    virtual void Log(std::FILE* file) override
    {
        Log(file, args);
    }
    private:
        std::tuple<Args...> args;

    // Sequence generator
    template <std::size_t... Idx>
    struct index {};

    template <std::size_t N, std::size_t... Idx>
    struct gen_seq : gen_seq<N - 1, N - 1, Idx...> {};

    template <std::size_t... Idx>
    struct gen_seq<0, Idx...> : index<Idx...> {};

    template <typename... Args>
    void Log(std::FILE* file, std::tuple<Args...>& tup)
    {
       Log(file, tup, gen_seq<sizeof...(Args)>{});
    }

    template <typename... Args, std::size_t... Is>
    void Log(std::FILE* file, std::tuple<Args...>& tup, index<Is...>)
    {
       fprintf(file, convert(std::get<Is>(tup))...);
    }
};

in the logger thread:

while(m_run)
{
   ....
   auto pTransaction = m_queue.pop();
   pTransaction->Log(file);
}

The logger is constantly crash. Here is the dump:

#2  0x0000000000497c63 in Log<char const (&) [57], std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, 0ul, 1ul, 2ul> (tup=..., file=0x1d00400, this=<optimized out>) at ./algo/orderd/../algoutil/include/algoutil/logger.hpp:122
#3  Log<char const (&) [57], std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&> (tup=..., file=0x1d00400, this=<optimized out>) at ./algo/orderd/../algoutil/include/algoutil/logger.hpp:116
#4  tt::algoutil::LogStringTransaction<char const (&) [57], std::string&, std::string const&>::Log (this=<optimized out>, file=0x1d00400)
at ./algo/orderd/../algoutil/include/algoutil/logger.hpp:95 

Looks like std::tuple does not make copy of all the arguments, it only holds a reference. If the object goes out of the scope, the Log function will cause Segmentation fault.

How do I solve the problem. how do I make a copy of all tuple items?

Aucun commentaire:

Enregistrer un commentaire