Я использую logger, который сохраняет print args в кортеж. кортеж используется в потоке журнала.std :: tuple args жизненный цикл?
class LogTransaction
{
public:
typedef std::unique_ptr<LogTransaction> Ptr;
LogTransaction() {}
virtual ~LogTransaction() {}
virtual void Log(std::FILE* file) = 0;
};
template<typename... Ts>
class LogTransaction : public LogTransaction
{
public:
template<typename... Args>
LogTransaction(Args&&... args) : m_args(std::forward<Args>(args)...) {}
~LogTransaction()
{
if (m_trd.joinable())
{
m_thrd.join();
}
}
virtual void Log(std::FILE* file) override
{
Log(file, m_args);
}
private:
template <class T> T convert(const T& val) { return val; }
const char* convert(const std::string& val) { return val.c_str(); }
// 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))...);
}
private:
std::tuple<Ts...> m_args;
};
class Logger
{
public:
Logger();
~Logger();
bool Start (const std::string& fileName)
{
m_file = std::fopen(fileName.c_str(), "a");
if (!m_file)
{
return false;
}
m_run.store(true);
m_thrd = std::move(std::thread([this]{ Run(); }));
return true;
}
void Stop()
{
m_run.store(false);
}
template<typename... Args>
inline void Log (Args&&... args)
{
m_queue.push(CreateTransaction(std::forward<Args>(args)...));
}
private:
void Run()
{
while(m_run)
{
std::list<LogTransaction::Ptr> transactions = m_queue.pop_all();
for (const auto& pTransaction : transactions)
{
pTransaction->Log(m_file);
fprintf(file, "\n");
fflush(file);
}
}
std::fclose(m_file);
}
template<typename... Args>
inline LogTransaction::Ptr CreateTransaction (Args&&... args)
{
LogStringTransaction<Args...>* pLogTransaction = new LogStringTransaction<Args...>(std::forward<Args>(args)...);
return std::move(LogTransaction::Ptr(pLogTransaction));
}
private:
std::thread m_thrd;
std::FILE* m_file;
std::atomic_bool m_run;
lockfree_queue<LogTransaction::Ptr> m_queue;
};
использование:
Logger logger();
Logger.start("test.log");
Logger.Log(....);
Регистратор постоянно врезаться. Вот свалка:
#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
в соответствии с дампом. std :: tuple ссылается на некоторые аргументы, потому что аргумент arg равен lvalue. Когда аргумент выходит за пределы области действия, Logger выйдет из строя, потому что он использует объект мусора.
Как сделать копию всех элементов кортежа?
Просьба указать [минимальный, полный и проверяемый пример] (http://www.stackoverflow.com/help/mcve). Я предполагаю, что вы держите ссылки на временные. – Barry
@Barry Я обновил код. Точно, кортеж содержит ссылку, если lvalue передано в функцию Log(). Мой вопрос: как мне сделать копию? – kzhdev